Tuckey urlrewrite, How to check is parameter with specified name exists? - tuckey-urlrewrite-filter

Seems the following configuration does not work
<rule>
<condition type="parameter" name="direct" operator="notequal"></condition>
<from>^/payment.html$</from>
<set name="google-analytics-uri">/shop/payment-direct</set>
</rule>
Enter url: _http://somesite.com/payment.html?direct=value
As result 'google-analytics-uri' is empty.

found solution(after debugging library sources:)
<rule>
<condition type="parameter" name="direct" operator="notequal">^$</condition>
<from>^/payment.html$</from>
<set name="google-analytics-uri">/shop/payment-direct</set>
</rule>

Related

Upgrading to jetty 9.4 replacing the HashSessionManager

After upgrading to jetty 9.4 I notice a ClassNotFoundException for org.eclipse.jetty.server.session.HashSessionManager.
I think I need to use a FileSessionDataStore but I don't see how that is suppose to be set on a SessionHandler.
The configuration I currently have is:
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
...
<Set name="sessionHandler">
<New class="org.eclipse.jetty.server.session.SessionHandler">
<Arg>
<New class="org.eclipse.jetty.server.session.HashSessionManager">
<Set name="storeDirectory">my/store/path</Set>
</New>
</Arg>
</New>
</Set>
</Configure>
I don't see what I need to do, SessionHandler doesn't take a SessionDataStore, but a SessionCache can be set on it but it looks like the implementations of SessionCache want a SessionHandler in the constructor, I don't see how to do that in XML.
In the jetty-9.4 session architecture, you have SessionHandler takes a SessionCache, which optionally takes a SessionDataStore.
See OneServletContextWithSession for a programmatic example.
That example uses the NullSessionDataStore, but the principle is the same as the FileSessionDataStore, which is the replacement for the old HashSessionManager ability to store sessions to disk.
The Jetty Documentation contains information on changes from previous versions of Jetty session management to the 9.4 style.
If you follow links in the documentation, you'll also find detailed info on the new session architecture.
As the documentation explains, the easiest way to configure sessions in jetty-9.4 when running in the distribution is to enable the appropriate module. However, if you're running embedded, or you just want to set up session management for a particular webapp in xml, here's some example code of setting up the FileSessionDataStore:
<Get id="sh" name="sessionHandler">
<Set name="sessionCache">
<New class="org.eclipse.jetty.server.session.DefaultSessionCache">
<Arg><Ref id="sh"/></Arg>
<Set name="sessionDataStore">
<New class="org.eclipse.jetty.server.session.FileSessionDataStore">
<Set name="storeDir">/tmp/sessions</Set>
</New>
</Set>
</New>
</Set>
</Get>
Ah I think I worked it out, it is not pretty it ended up as:
<Set name="sessionHandler">
<New class="org.eclipse.jetty.server.session.SessionHandler">
</New>
</Set>
<Call name="getSessionHandler" id="sessionHandler" />
<Ref refid="sessionHandler">
<Set name="SessionCache">
<New class="org.eclipse.jetty.server.session.DefaultSessionCache">
<Arg>
<Ref refid="sessionHandler"/>
</Arg>
<Set name="SessionDataStore">
<New class="org.eclipse.jetty.server.session.FileSessionDataStore">
<Set name="StoreDir">my/store/path</Set>
</New>
</Set>
</New>
</Set>
</Ref>
I followed the easier to read pure java example I found at http://useof.org/java-open-source/org.eclipse.jetty.server.session.FileSessionDataStore
If this doesn't look correct to a Jetty expert I am happy to edit the answer so as not to mislead others.

Jetty MDC handler doesn't provide contextPath

Jetty 9.3.8.v20160314 running on AWS EC2 Linux machine with Java 1.8.0_51 has two web apps under two different dir+context.xml - webapps/app1 and webapps/app2 with an empty webapps/ROOT directory.
I'm trying to get each webapp to have a separate log with contextPath in its name.
Each app has the following webapps/appX.xml context defined -
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/appX</Set>
<Set name="war">
<SystemProperty name="jetty.home" default="."/>/webapps/appX
</Set>
</Configure>
Followed Example: Centralized Logging with Logback and installed webapp-logging module, app is using slf4j Logger and resources/logback.xml is -
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %t %c{0} [%p] %m%n</pattern>
</encoder>
</appender>
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<key>contextPath</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="FILE-${contextPath}" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${jetty.home}/logs/${contextPath}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>${contextPath}_%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %t %c{0} [%p] %m%n</pattern>
</encoder>
<append>true</append>
</appender>
</sift>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="SIFT"/>
</root>
</configuration>
But it all goes to unknown.log. Using servername instead works well and creates separate file for each domain being used to access the server.
So it would seem that contextPath isn't properly assigned by ContextLogHandler.
Why is it empty?

Negative response time in Jetty server access log

I'm running on Jetty and my access log is configured to show the response time.
today I noticed that a very minimal amount of the requests (about 30 out of 600K) have a negative response time and I was wondering if anyone ever encountered such a behavior.
This is a sample of my response:
<[IP]> - - <[date]> "POST <[url]> HTTP/1.0" 201 461 -18096
In case you want to identify this in the access log - this is the grep command i used:
grep --color "-[0-9][0-9]*" server-access.2013_12_09.log
Jetty Version: 8.1.8
Setup in jetty.xml:
<New id="request-log-handler" class="org.eclipse.jetty.server.handler.RequestLogHandler">
<Set name="requestLog">
<New class="org.eclipse.jetty.server.NCSARequestLog">
<Arg>
<Property name="logging.httpAccessLog" default="logs/app-access.yyyy_mm_dd.log" />
</Arg>
<Set name="retainDays">
<Property name="logging.accessLogRetentionInDays" default="10" />
</Set>
<Set name="append">
<Property name="logging.httpAccessLogAppend" default="true" />
</Set>
<!-- logs referer and user agent -->
<Set name="extended">
<Property name="logging.httpAccessLogExtended" default="false" />
</Set>
<!-- response time -->
<Set name="logLatency">
<Property name="logging.httpAccessLogLatency" default="true" />
</Set>
</New>
</Set>
Using Jetty 9.1.0.
Key:
<name> = optional / configurable entry on line
{name} = mandatory entry
<servername> {X-Forwarded-For||remote-addr} - {authentication/principal/name} [{request-timestamp}] "{method} {uri} {protocol}" {response-status-code} {response-content-length} <extended-log> <cookies> <latency>
Where:
<servername> can be the request/Host header
<extended-log> can be "{referer} {user-agent}"
<cookies> can be " -" or "{cookie.name}={cookie-value};"
<latency> can be (now - request.getTimeStamp())
Interestingly, it appears that your system clock adjusted during a request. A full 18 seconds!
Here's why this is the leading theory ...
The request.timestamp is set when the request starts, then the latency is computed later during the access/request logging. For there to be a negative value, either something outside of Jetty itself reset the request.timeout, or the system clock changed.

How to get Jetty to use JVM scoped JNDI?

I'm trying to setup a JNDI resource for a Jackrabbit repository factory in Jetty. The problem is that I seem to be getting thhe JNDI as webapp scoped. I need it to be JVM scoped. As far as I understood from the docs, you need to specify a null arg as shown below (<Arg></Arg>) in order to do so (explained here).
I have two webapps deployed to Jetty and I need them to be sharing the same JNDI. If they're not sharing it, Jackrabbit tries to get initialized twice and fails which breaks my whole app.
I ran the code through a debugger and I can see that the first webapp that gets accessed and needs a JNDI lookup for the Jackrabbit repository, gets an instance of the BindableRepositoryFactory and correctly adds records to the cache object. However, a completely different object is created for the cache upon JNDI lookup. That is obviously still empty and thus a new instance gets created, which screws things up.
I am using Jetty 7.6.2.v20120308.
Here's my jetty-jndi.xml:
<New class="org.eclipse.jetty.plus.jndi.Resource">
<Arg></Arg>
<Arg>jndi:comp/env/jcr/repository</Arg>
<Arg>
<New class="javax.naming.Reference" id="reference">
<Arg>javax.jcr.Repository</Arg>
<Arg>org.apache.jackrabbit.core.jndi.BindableRepositoryFactory</Arg>
<Arg>null</Arg>
<Call name="add" id="reference">
<Arg>
<New class="javax.naming.StringRefAddr">
<Arg>configFilePath</Arg>
<Arg><SystemProperty name="jetty.home" default="."/>/jackrabbit/repository.xml</Arg>
</New>
</Arg>
</Call>
<Call name="add" id="reference">
<Arg>
<New class="javax.naming.StringRefAddr">
<Arg>repHomeDir</Arg>
<Arg><SystemProperty name="jetty.home" default="."/>/jackrabbit</Arg>
</New>
</Arg>
</Call>
</New>
</Arg>
</New>
In the pom file where I'm invoking jetty from, I have the following relevant settings that tell Jetty to use the JNDI and Plus settings xml-s:
<jettyConfig>${project.build.directory}/jetty/etc/jetty-plus.xml,${project.build.directory}/jetty/etc/jetty-jndi.xml</jettyConfig>
In the jetty-plus.xml I have:
<!-- =========================================================== -->
<!-- Sequence of configurations to defining Plus features. -->
<!-- =========================================================== -->
<Array id="plusConfig" type="java.lang.String">
<Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
<Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
<Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
<Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item> <!-- Add for JNDI -->
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item> <!-- Add for JNDI -->
<Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
<Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
<Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item> <!-- Not needed for Jetty-8 -->
</Array>
<!-- =========================================================== -->
<!-- Apply plusConfig to all webapps for this Server -->
<!-- =========================================================== -->
<Call name="setAttribute">
<Arg>org.eclipse.jetty.webapp.configuration</Arg>
<Arg>
<Ref id="plusConfig"/>
</Arg>
</Call>
Any ideas what I might be doing wrong?
Many thanks in advance! :)
This appears to be a bug in Jetty's global JNDI resource configuration.
I have filed a bug in Jetty's bugzilla and will accept this answer as correct, despite the fact it is no solution.

Map external directory to web.xml

Is there an easy way to map a directory in the web.xml or other deployment descriptor (jetty.xml, etc) files?
For example, if I have a directory /opt/files/ is there a way that I can access its files and sub-directories by visiting http://localhost/some-mapping/? It strikes me that there should be some simple way of doing this, but I haven't been able to find out how (via google, stackoverflow, etc). All I've found are servlets that mimic fileservers, which is not what I would like.
For reference I am using jetty on an AIX box.
No idea how to do it with Jetty, but in Tomcat you can just add a new <Context> to server.xml:
<Context docBase="/opt/files" path="/files" />
This way it's accessible by http://example.com/files/.... See if something similar exist for Jetty.
Update: after Googling, the "normal Java code" equivalent would be something like:
WebAppContext files = new WebAppContext("/opt/files", "/files");
Server server = new Server(8080);
server.setHandler(files);
server.start();
Now yet to translate that into jetty.xml flavor. I am a bit guessing based on the documentation and examples found on the web, so don't pin me on it:
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="webApp">/opt/files</Set>
<Set name="contextPath">/files</Set>
</Configure>
Another possibility may be this:
<Configure class="org.mortbay.jetty.Server">
<Call name="addHandler">
<Arg>
<New class="org.mortbay.jetty.webapp.WebAppContext">
<Arg name="webApp">/opt/files</Arg>
<Arg name="contextPath">/files</Arg>
</New>
</Arg>
</Call>
</Configure>
After some more fiddling around, the best way to do this (for jetty) is to deploy a descriptor in the context directory that looks like the following...
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!-- Configuration of a custom context. -->
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
<Call class="org.eclipse.jetty.util.log.Log" name="debug">
<!-- The default message to show if our context breaks. -->
<Arg>Configure context.xml</Arg>
</Call>
<!--
The context path is the web location of the context in relation to the
server address.
-->
<Set name="contextPath">/context</Set>
<!--
The resource base is the server directory to use for fetching files.
-->
<Set name="resourceBase">/path/to/files/on/server</Set>
<Set name="handler">
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="directoriesListed">true</Set>
<!-- For now we don't need any welcome files -->
<!--
<Set name="welcomeFiles"> <Array type="String">
<Item>index.html</Item> </Array> </Set>
-->
<!--
The cache time limit in seconds (ie max-age=3600 means that if the
document is older than 1 hour a fresh copy will be fetched).
-->
<Set name="cacheControl">max-age=3600,public</Set>
</New>
</Set>
</Configure>
I hope that this helps someone else!
I don't know that you can do that as a URL mapping, however files and folders in the same directory that your web.xml file is in will be accessible in the way you describe, although you can't control the mapping under your webapp.
Does that suit your needs?