Tag: jetty

  • Adding X-Powered-By, Version, and Date Headers to ORDS Standalone

    Additional functionality with Jetty XML

    Here is an example of a Jetty Context XML file that adds additional headers to your ORDS HTTP responses.

    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_10_0.dtd">
    <Configure id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
        <Set name="sendXPoweredBy">
          <Property name= "jetty.send.xpoweredBy" default="true" />
        </Set>
        <Set name="sendServerVersion">
          <Property name="jetty.send.server.version" default="true" />
        </Set>
        <Set name="sendDateHeader">
          <Property name="jetty.send.date.header" default="true" />
        </Set>
    </Configure>

    Note

    This example is designed to show how you might structure a Jetty Content XML file to add additional functionality to ORDS’ embedded Jetty server. I’m using ORDS in standalone mode, so if you are using Apache Tomcat or Weblogic, this will not work.

    To test this out, first, create a Jetty XML file and populate the body with the contents in the above example. In this example, I’ve named the file jetty_headers.xml.

    Next, place the file in your /etc folder1. Once there, start ORDS back up (i.e., ords serve). I have installed and deployed ORDS locally (i.e., localhost), with my configuration folder named configuration. With the full path being:

    /Users/choina/ords/configuration/global/standalone/etc/jetty_headers.xml

    For reference, here is a view of how my ORDS configuration folder is structured:

    .
    ├── databases
    │   └── default
    │       ├── pool.xml
    │       └── wallet
    │           └── cwallet.sso
    └── global
        ├── settings.xml
        └── standalone
            ├── access_logs
            ├── etc
            │   └── jetty_headers.xml
            ├── self-signed.key
            └── self-signed.pem

    With everything in place, I can issue a request to one of my ORDS endpoints. In this case, I’ve created a simple GET Handler that queries the EMP table. The actual response isn’t the focus, but rather the response headers.

    I used cURL for this:

    curl http://localhost:8080/ords/hr/employees/

    In the response, I now see three new response headers displayed in a console output2:

    Server: Jetty(12.0.18)

    X-Powered-By: Jetty(12.0.18)

    Date: Sat, 24 2025 11:46:12 GMT

    Below is a console log printout showing the full details of the request and response (excluding the response body):

    * Preparing request to http://localhost:8080/ords/hr/employees/
    * Current time is 2025-05-24T11:46:12.857Z
    * Enable automatic URL encoding
    * Using default HTTP version
    * Enable timeout of 30000ms
    * Enable SSL validation
    * Connection 9 seems to be dead
    * Closing connection 9
    * Hostname in DNS cache was stale, zapped
    *   Trying 127.0.0.1:8080...
    * Connected to localhost (127.0.0.1) port 8080 (#10)
    
    > GET /ords/hr/employees/ HTTP/1.1
    > Host: localhost:8080
    > User-Agent: insomnia/11.1.0
    > Accept: */*
    
    * Mark bundle as not supporting multiuse
    
    < HTTP/1.1 200 OK
    < Server: Jetty(12.0.18)
    < X-Powered-By: Jetty(12.0.18)
    < Date: Sat, 24 May 2025 11:46:12 GMT
    < Content-Type: application/json
    < X-ORDS_DEBUG: true
    < ETag: "yGRRTja1S+tUjM5cGRS/a6WnUiHoqAczoKJ0J5Ty9sAGg1QeeXN3G+BtUukHu9DWgxrpOAOaapoBAd++rVdl6g=="
    < Transfer-Encoding: chunked
    
    
    * Received 8.2 KB chunk
    * Received 7 B chunk
    * Connection #10 to host localhost left intact

    Conclusion

    Arguably, the Server, X-Powered-By, and Date response headers could be considered functionally useless. However, for logging purposes, especially when it comes to huge applications or microservices more data can aid in quicker root-cause analyses.

    In any case, pretty neat how you can easily add enhanced functionality to ORDS standalone with a few lines of XML.

    References

    Footnotes

    1. You need to create this `/etc` folder manually. As of ORDS 25.1, this folder isn’t something that already exists. You might have a path similar to the one I shared above. ↩︎
    2. You may notice the Date header is returned in GMT/Zulu. This will always be the case with ORDS. ORDS will always return data and times in GMT/Zulu format. For reference, if you independently alter the `user.timezone` JVM Option, this would only change how ORDS interprets dates and times where no timezone is attached. The Oracle Database `Date` and `Timestamp` datatypes are two examples where the timezone is not indicated. ↩︎
  • ORDS Standalone: specifying a response header with jetty.xml

    NOTE: A Load Balancer or Reverse Proxy can achieve this same result. If your current ORDS deployment consists of either, you may prefer to add header "rules" there instead.
    Should you choose to operate ORDS in Standalone mode, you can rely on the Jetty server to provide this header rule. See the this section of my latest article for configuring the /etc folder.

    Start here

    Once you have created the /etc folder, save the following code block as a XML file using an easily recognizable file name.

    <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
    <Configure id="Server" class="org.eclipse.jetty.server.Server">
      <Call name="insertHandler">
      <Arg>
        <New class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
          <Get id="Rewrite" name="ruleContainer" />
          <Call name="addRule">
            <Arg>
              <New id="header"  class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
                <Set name="pattern">*</Set>
                <Set name="name">Strict-Transport-Security</Set>
                <Set name="value">max-age=31536000;includeSubDomains</Set>
              </New>
            </Arg>
          </Call>
        </New>
      </Arg>
    </Call>
    </Configure>

    In this example, we use jetty-response.xml as the file name. With this file included in the /etc directory, ORDS will “pick up” this configuration setting during runtime.1

    Some details of this file

    This jetty-response.xml file will enable ORDS Standalone to include the Strict-Transport-Security header name and its values max-age=3153600;includeSubDomains in each response to a request.2 In lay terms this XML file establishes a new Jetty response header, named Strict-Transport-Security, it applies to its responses for all requests (denoted by the *), and this header’s value is comprised of the following:

    • max-age=31536000;
    • includeSubDomains

    To illustrate this behavior, consider the following curl command and subsequent response. A request is sent to a resource (in this case /departments_json) and the subsequent ORDS response includes:

    1. a JSON payload
    2. the typical/standard headers, and
    3. additional headers indicated in the jetty-response.xml file

    And that’s it, you’ve yet again customized the Jetty server (that is responsible for ORDS Standalone)!

    That’s it for now

    Similarly to the Jetty Access Log example, these XML files can be a quick and easy way to introduce additional functionality into your ORDS Stand-Alone deployment. What else can you imagine? Take a look at the Jetty APIs for inspiration. Did you know you can extend ORDS with plugins, too?

    And of course, obligatory ORDS resources: Download ORDS | Oracle ORDS forum | ORDS Docs | ORDS playlist

    Follow

    And don’t forget to follow, like, subscribe, share, taunt, troll, or stalk me!

    Footnotes

    1. What the hell is runtime? Having no formal education in software engineering, my understanding is that runtime has to do with the execution of a program. Runtime relates to the initial and continued execution of the program. In the case of these XML files, the instructions therein are not formally part of the Jetty server but are included in the instructions when you issue the ords serve command. Doing so effectively starts up the Jetty web server. Jetty then recognizes there are files in the /etc folder and includes them when it enters into “runtime” or the “runtime environment.” This Wikipedia post is a great place to start. But I certainly wouldn’t use that as the “official” definition. This stackoverflow thread is extremely helpful as well. ↩︎
    2. Strict-Transport-Security (about this header) is a response header. This header is used to inform the browser that HTTPS should only be used to access ORDS resource/s. You’ve probably seen * used in the ORDS documentation. In this case, <Set name="pattern">*</Set> found in the XML file is used * as a wildcard (i.e. I interpret this as “apply this rule to everything and anything.”). The <Set name="value">max-age=31536000;includeSubDomains</Set> line includes the “directives”: max-age=3153600; and includeSubDomains. Examples of subdomains would be something like: en.wikipedia.org, where en (English language) is a subdomain of wikipedia.org; more details here. ↩︎