How to set a dynamic Expires header in Jetty? - jetty

Jetty allows headers to be set using the jetty-rewrite functionality, but it doesn't appear to be very smart, and only accepts a fixed string.
How do I tell Jetty to send an "expires in 8 hours" header?
With Apache .htaccess and mod_expires you can do "access plus 8 hours" but of course Jetty doesn't understand .htaccess files, nor can I find any info on a similar construct in jetty-rewrite.xml
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
<Set name="pattern">*.png</Set>
<Set name="name">Expires</Set>
<Set name="value">access plus 8 hours</Set>
</New>
</Arg>
</Call>
That just sends the literal text "access plus 1 day" back, which is of course ignored by the client.
Could/should this be done with a servlet filter? Jetty has a Gzip filter but doesn't appear to offer something similar for dynamically setting headers.

That could be a nice feature..
Open an enhancement for it at bugs.eclipse.org under RT/Jetty. Patches are welcome, either attached to the bug or pushed into our gerrit instance.
That being said...the jetty xml is really an xml layer over java so I suspect you could actually so this in java if you can find the APi for it. I think there is a joda time library that has a method where you could wire up something that would call new DateTime().plusHours(8) to populate that value.
Probably better to add it as a feature though.

Related

Jetty Static resources dont respect the file permission (read specifically) when listing

I have a simple xml context to display static files. The server loads fine and the page to show files loads as expected. The issue is that file with permission 000 are still showing in the list. If I click on one of the files I get a java stack trace error saying that jetty does not have permission to read the file (because it doesnt).
Does anyone know how to get these files with no read permission to not show up?
I am using jetty distribution version 9.4.34.v20201102. I run jetty as a service and have JETTY_USER set in /etc/default/jetty.
Here is my simple context in JETTY_BASE/webapps/static.xml
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
<Set name="contextPath">/</Set>
<Set name="handler">
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="resourceBase">/mshr/test/</Set>
<Set name="directoriesListed">true</Set>
</New>
</Set>
</Configure>
This is not supported by the Jetty ResourceHandler, the ResourceService, or the DefaultServlet.
Asking about file permissions during file listing is actually quite an expensive thing to do (depending on the file system).
That's why Jetty doesn't do that.
If you feel otherwise, file a request at https://github.com/eclipse/jetty.project/issues

Overwriting jetty default ciphers

My initial problem was that when I was using IncludeCipherSuites option in jetty configuration file, only TLS 1.2 was being supported. Please see below post for details:
Jetty IncludeCipherSuites enables only TLS 1.2
Based on the comments it appeared that if I don't provide ExcludeCipherSuites in my jetty configuration file, jetty default exclude cipher list is being used and many ciphers which I explicitly enabled by IncludeCipherSuites option were being excluded (if they are in jetty default exclude list).
Just adding an empty ExcludeCiphersSuites tag together with IncludeCipherSuites tag in the same configuration file solved the problem. By saying empty I mean I didn't add any ciphers to exclude, I just added ExcludeCiphersSuites tag with empty list of ciphers:
<Set name="ExcludeCipherSuites">
<Array type="String">
</Array>
</Set>
My understanding is that previously (with only IncludeCipherSuites option) some of the the ciphers which I was including was being excluded by jetty default exclude list. However adding ExcludeCiphersSuites option with empty list forces to overwrite jetty's default exclude list with an empty list, so nothing is being excluded from my list of include ciphers. Can you please confirm that my understanding is correct?
Also based on all the above findings say jetty has the below default configuration for ciphers:
Jetty default exclude ciphers: CIPHER1, CIPHER2
Jetty default include ciphers: CIPHER3, CIPHER4
I want to configure my jetty to support CIPHER1 and CIPHER5 ONLY. Is the below the correct configuration I should use?
<Set name="ExcludeCipherSuites">
<Array type="String">
</Array>
</Set>
<Set name="IncludeCipherSuites">
<Array type="String">
<Item>CIPHER1</Item>
<Item>CIPHER2</Item>
</Array>
</Set>
Will this overwrite all jetty defaults and force jetty to support CIPHER1 and CIPHER2 and nothing else?
Jetty does not disable the protocols TLS/1.0 or TLS/1.1.
The configuration of protocols, ciphers, keystores, truststores, etc is all controlled by the SslContextFactory
The SslContextFactory has the ability to disable protocols, using the Include/Exclude of Protocols using configurations like addExcludeProtocols()
Note that Jetty does not include TLS/1.0 or TLS/1.1 in its default exclusions.
As of Jetty 9.3.13.v20161014 the default exclusion of protocols is as follows:
addExcludeProtocols("SSL", "SSLv2", "SSLv2Hello", "SSLv3");
Since you seem to be asking specifically about Cipher Suites, know that the Jetty 9.3.13.v20161014 default exclusions for Cipher suites is as follows:
setExcludeCipherSuites("^.*_(MD5|SHA|SHA1)$");
This happens to be the same set of cipher suites that were declared vulnerable back in 2008, and will cease to be used on Chrome and Firefox clients on Jan 1, 2017. This kill switch for MD5/SHA/SHA1 is present in all versions of Chrome and Firefox released in the last few (5-ish?) years.
Note also that Java itself disables various protocols and cipher suite algorithms.
$ grep -E "^jdk.*disabled" $JAVA_HOME/jre/lib/security/java.security
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768

Jetty 6 to Jetty 9 Context Deployer migration

Migrating from Jetty 6 to 9 has been much harder than what I originally thought but I have got a lot of it done thanks to the resources you all have online
I question that I have not found xml examples online regarding Embedded Servlets in Jetty 9 other than the link below
http://jetty.4.x6.nabble.com/Jetty-9-Context-Deployer-td4960157.html
First off, it seems that you all have migrated from ContextDeployer to WebAppProvider is this a correct statement?
I ask this because in Jetty6, I was able to use a context deployer to search a directory to configure servlets as context objects. Since ContextDeployers seem to be gone, the closest usage in Jetty I see is the WebAppProvider which opens webpages from a war file. This isn't what my company wants to do and we would like to be able to use contexts in the same way we have done in the past
Now I have seen the ServletContextHandler which seems simple enough to configure and would act as the context object. However, my current web app provider configuration will not open my servlet web pages
Here is an excerpt of how I use the DeployManager in xml
<Call name="addBean">
<Arg>
<New id="DeploymentManager" class="org.eclipse.jetty.deploy.DeploymentManager">
<Set name="contexts">
<Ref refid="Contexts" />
</Set>
<Call id="webappprovider" name="addAppProvider">
<Arg>
<New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
<Set name="monitoredDirName"><Property name="jetty.home" default="config/jetty/context/"/></Set>
<Set name="scanInterval">5</Set>
</New>
</Arg>
</Call>
</New>
</Arg>
An example Servlet configuration xml
<Configure id="contexts" class="org.eclipse.jetty.servlet.ServletContextHandler">
<Set name="contextPath">/</Set>
<Call name="addServlet">
<Arg>class.name.here</Arg>
<Arg>/*</Arg>
</Call>
</Configure>
You can use the WebAppProvider in exactly the same way that ContextDeployer was previously used. Specifically if you put a context.xml file into the webapp directory, it will be hot deployed exactly as it was with the ContextDeployer.
As for the type of the Context you wish to deploy, it an be just a ContextHandler, a ServletContextHandler, a WebAppContext or anything else that extends ContextHandler
Look in the demo-base/webapps directory for some examples.
In your example, I'm guessing that the id="contexts" might be the problem. Try removing it as you don't need an id there. Other than that, it looks like it should work, so you are on the right path.

Access to ServletContext from PushStrategy

I try to implement a custom PushStrategy, which is an API related to server push support of SPDY protocol inside Jetty.
I implement the following method:
public Set<String> apply(Stream stream, Fields requestHeaders, Fields responseHeaders);
However I need to access the ServletContext inside the method call but I don't know how I can access it.
I'm investigating a way to inject the WebAppContext in jetty.xml:
<New id="pushStrategy" class="spdy.MyPushStrategy">
<Set name="webAppContext">
<Ref id="..." />
</Set>
</New>
The problem is that this configuration step is in the Server block declared in jetty.xml:
<Configure id="Server" class="org.eclipse.jetty.server.Server">....</Configure>
while WebAppContext is configured in jetty-web.xml
<Configure id="WebAppContext" class="org.eclipse.jetty.webapp.WebAppContext">
I don't know how to refer any existing WebAppContext ID in this file.
Here is my maven plugin config:
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-version}</version>
<configuration>
<stopPort>8888</stopPort>
<stopKey>quit</stopKey>
<jvmArgs>
-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn-version}/npn-boot-${npn-version}.jar
</jvmArgs>
<webAppConfig>
<jettyEnvXml>${basedir}/src/main/config/jetty-web.xml</jettyEnvXml>
</webAppConfig>
<jettyXml>${basedir}/src/main/config/jetty.xml</jettyXml>
<contextPath>/</contextPath>
</configuration>
When you create a WebAppContext via an XML file, such as what is described in the Configuring a Specific WebApp Deployment.
You can configure an id attribute for that particular webapp's <Configure> element.
Example:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN"
"http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="myapp1" class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/wiki</Set>
<Set name="war">/opt/myapp/myapp.war</Set>
</Configure>
Then you can use the Jetty XML notation you described to reference that particular webapp.
<New id="pushStrategy" class="spdy.MyPushStrategy">
<Set name="webAppContext">
<Ref id="myapp1" />
</Set>
</New>
Now, back to your more specific concern, access to the ServletContext from the PushStrategy implementation.
That cannot be done from a PushStrategy implementation, as it is too high-level in the layering of the TLS -> SPDY (with PushStrategy) -> Connector -> Connection -> HTTP -> Request -> Handlers -> WebAppContext -> ServletContext -> Servlet.
You might be able to split up the behavior though.
Create a CustomPushFilter that your Servlet context has, it has the logic on what you want to associate for the push, done via a custom response header. Then your CustomPushStrategy could look for those response headers to know how to associate those extra resources. Bonus with this approach is that your Servlets could even automatically add resources for push based on servlet specific knowledge.

How do i configure Railo on Jelastic (PAAS) to work with multiple domains using Jetty?

How do i configure Railo on Jelastic (PAAS) to work with multiple domains using Jetty?
I found the configuration for Railo using Tomcat, but I would like to use Jetty because of the memory requirements
Thanks
In Jelastic there are at least 2 possible ways of binding your domain name.
Actually you can bind your domain by deploying your application to a specified context ROOT via Jelastic dashboard. Here is an article which explains how to manage it: http://jelastic.com/docs/custom-domains
The second way is to set DNS A Record. The given article explicitly shows how to do it: http://jelastic.com/docs/A-Records-domain-names
I am not sure on the Jelastic specific side, but with Jetty you can create an XML file in the contexts folder, and it should look something like this:
contexts/Localhost.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/</Set>
<Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/webapps/railo/</Set>
<Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>
<!-- virtual hosts -->
<Set name="virtualHosts">
<Array type="String">
<Item>localhost</Item>
<Item>127.0.0.1</Item>
</Array>
</Set>
</Configure>
You can then create more files in there for each domain, making sure you add/edit the entries for the resourceBase (your file webroot) and in the Item for the virtual host.
I am not sure how Jelastic handles this stuff with Jetty specifically, but if you can edit the files you should be cool.