JDK6 Support
by Jason Greene
Is there anyone using undertow on JDK6, and cares that we continue to support it? We are considering dropping it.
--
Jason T. Greene
WildFly Lead / JBoss EAP Platform Architect
JBoss, a division of Red Hat
10 years, 6 months
HttpServletRequestImpl.authenticate (incorrectly?) closes response upon false outcome
by arjan tijms
Hi,
When an authentication mechanism (e.g. a JASPIC SAM) did not actually
authenticate following a call to HttpServletRequest#authenticate, Undertow
closes the stream.
This happens in
io.undertow.servlet.spec.HttpServletRequestImpl.authenticate(HttpServletResponse)
via the following code fragment:
if (sc.authenticate()) {
...
} else {
// Not authenticated and response already sent.
HttpServletResponseImpl responseImpl =
exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getOriginalResponse();
responseImpl.closeStreamAndWriter();
return false;
}
I'm not 100% sure why it closes the response stream (or writer) here. The
Javadoc for HttpServletRequest#authenticate doesn't say this happens and
it's not in the Servlet spec either.
Most importantly perhaps, it's not what JBoss AS 7/EAP 6 does. I don't
think any other server actually does this (but have to investigate to be
sure).
It looks like Undertow assumes that the authentication mechanism always
sets all headers and commits the response, but the contract as expressed in
its Javadoc seems weaker:
"Use the container login mechanism configured for the ServletContext to
authenticate the user making this request.
This method *may* modify and commit the argument HttpServletResponse."
(note the phrasing "may")
As with many things in Servlet it's not entirely clear whether for the case
that the method returns "false" the response "must" have been modified and
committed, but whether this is the case or not, I don't think it says
anywhere that after a call to this method nothing can be written to the
response any more.
Furthermore, this also doesn't behave very well when a (wrapped) response
is passed in, as it closes the original response, not the one passed in.
Kind regards,
Arjan
10 years, 6 months
javadoc style
by Bernd Eckenfels
Hallo,
for the following minor JavaDoc pull request I wonder about the
paragraph style:
https://github.com/ecki/undertow/commit/9fae96a2d43dcd6de0be0755babd9c462...
It seems that most, but not all other Javadocs use a "self closing"
XHTML "<p/>", whereas Oracle seems to go the HTML route and javadoclint
regards them as error.
I have also seen some javadoc comments with empty lines and no <p> at
all. And finally there are some <p>line</p>, even for the first line.
What is the prefered style? I personally like the html style:
* First sentence.
* <p>
* More text on its own paragraph.
* Can have line breaks which are ignored by Javadoc.
* <p>
* Just like this.
* <p>
* Linebreaks like these<br>
* should be avoided.
In case my <p> style is the problem which blocks the PR from beeing
merged, let me known.
Gruss
Bernd
10 years, 6 months
Re: [undertow-dev] [undertow] Change to using a timer to invalidate the date rather than calling nanoTime each request (07e3b93)
by Bernd Eckenfels
Hello Stuart,
yes I agree it is a good compromise. I do wonder however if you should
use an atomic to set the new value to make sure you schedule only one
timer. I could imagine that it creates an avalanch of timers if 2
requests at the same time race to set the next date (and start 2
timers) and then the next expire 2x2 timers, etc.
(And I would also move the calculations for mod+togo after setting the
new dateString to make the window smaller
Gruss
Bernd
Am Wed, 04 Jun 2014
09:52:18 -0700 schrieb Stuart Douglas <notifications(a)github.com>:
> Stuart Douglas <notifications(a)github.com>
> To: undertow-io/undertow <undertow(a)noreply.github.com>
> Cc: Bernd <bernd(a)eckenfels.net>
> Subject: Re: [undertow] Change to using a timer to invalidate the
> date rather than calling nanoTime each request (07e3b93) Date: Wed,
> 04 Jun 2014 09:52:18 -0700 Reply-To: undertow-io/undertow
> <reply+c-6555558-99b5c22664ba7984b00186177b011624000c5527-361432(a)reply.github.com>
>
> The main issue I had with that is that it will run even if your
> server is completely idle, and also that it adds additional lifecycle
> complexity into the connectors, as they would need to have their
> timers explicitly stopped on teardown. I think this is a good
> compromise.
>
> ---
> Reply to this email directly or view it on GitHub:
> https://github.com/undertow-io/undertow/commit/07e3b9315c3d87205ef5ac8907...
10 years, 6 months
Nonce Format of SimpleNonceManager (UTF8)?
by Bernd Eckenfels
Hello,
I was a bit confused about the use of UTF-8 for converting a number to
bytes, but when I looked more closely, it is even more confusing why a
decimal number is used and converted here at all. If I understand it
right the format of the bytes and the length is unconstrained? I would
recommend to use 7 byte array with binary content. But even using Hex
or radix=36 strings would reduce the byte[] size without losing
entropy.
private Nonce createNewNonce(NonceHolder previousNonce) {
byte[] prefix = new byte[8];
random.nextBytes(prefix);
long timeStamp = System.currentTimeMillis();
byte[] now = Long.toString(timeStamp).getBytes(UTF_8);
String nonce = createNonce(prefix, now);
->
byte[] now =
Long.toString(timeStamp,36).getBytes(StandardCharsets.ISO_8859_1)
This makes the byte array shorter and the conversion slightly faster,
here are the timing for the various byte encoders on different string
formats (base-10,16,32,36) (8threads):
Benchmark (number) Mode Samples Score Score error Units
n.e.t.l.MyBenchmark.testGetBytesASCII 1401994160926 thrpt 80 4932,143 41,752 ops/ms
n.e.t.l.MyBenchmark.testGetBytesASCII 1466d5d2b1e thrpt 80 5270,165 64,343 ops/ms
n.e.t.l.MyBenchmark.testGetBytesASCII 18pmlqaou thrpt 80 5521,322 119,856 ops/ms
n.e.t.l.MyBenchmark.testGetBytesASCII hw2f4hzy thrpt 80 5929,315 62,562 ops/ms
n.e.t.l.MyBenchmark.testGetBytesBase 1401994160926 thrpt 80 154669,919 3845,919 ops/ms
n.e.t.l.MyBenchmark.testGetBytesBase 1466d5d2b1e thrpt 80 155290,761 1678,557 ops/ms
n.e.t.l.MyBenchmark.testGetBytesBase 18pmlqaou thrpt 80 152989,174 5648,101 ops/ms
n.e.t.l.MyBenchmark.testGetBytesBase hw2f4hzy thrpt 80 154360,497 3022,226 ops/ms
n.e.t.l.MyBenchmark.testGetBytesDefault 1401994160926 thrpt 80 2319,440 47,902 ops/ms
n.e.t.l.MyBenchmark.testGetBytesDefault 1466d5d2b1e thrpt 80 2648,794 29,700 ops/ms
n.e.t.l.MyBenchmark.testGetBytesDefault 18pmlqaou thrpt 80 3098,998 36,169 ops/ms
n.e.t.l.MyBenchmark.testGetBytesDefault hw2f4hzy thrpt 80 3364,678 33,274 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLATIN1 1401994160926 thrpt 80 5202,078 189,594 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLATIN1 1466d5d2b1e thrpt 80 6166,294 64,541 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLATIN1 18pmlqaou thrpt 80 6677,003 130,301 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLATIN1 hw2f4hzy thrpt 80 6293,458 331,745 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLower 1401994160926 thrpt 80 10332,605 114,527 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLower 1466d5d2b1e thrpt 80 10173,196 120,769 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLower 18pmlqaou thrpt 80 10392,109 150,898 ops/ms
n.e.t.l.MyBenchmark.testGetBytesLower hw2f4hzy thrpt 80 10584,135 140,522 ops/ms
n.e.t.l.MyBenchmark.testGetBytesUTF8 1401994160926 thrpt 80 4998,594 115,126 ops/ms
n.e.t.l.MyBenchmark.testGetBytesUTF8 1466d5d2b1e thrpt 80 5184,154 72,303 ops/ms
n.e.t.l.MyBenchmark.testGetBytesUTF8 18pmlqaou thrpt 80 5395,096 98,476 ops/ms
n.e.t.l.MyBenchmark.testGetBytesUTF8 hw2f4hzy thrpt 80 5212,183 142,887 ops/ms
(Lower=loop over char array and use lower byte)
However I wonder if longToLower7Bytes(now) would be even more efficient?
Both changes needs to be reflected in verifyUnknownNonce() as well.
This would benefit from a byte nonce as well, as you could for example
not anymore trigger NumberFormatException with invalid nonces.
Want me to provide a binary version? How would the compatibility be
handled? (Using base10+ASCII is compatible, all other changes not). The native version minimizes the GC load as well:
Benchmark (number) Mode Samples Score Score error Units
n.e.t.l.MyBenchmark.testGetBytesNative 1401994160926 thrpt 80 31669,314 260,181 ops/ms
n.e.t.l.MyBenchmark.testGetBytesString 1401994160926 thrpt 80 2621,683 38,270 ops/ms
@GenerateMicroBenchmark
public byte[] testGetBytesNative() {
byte[] res = new byte[8];
long num = number;
for(int i=7;i>=0;i--)
{
res[i] = (byte)(num & 255);
num >>= 8;
}
return res;
}
@GenerateMicroBenchmark
public byte[] testGetBytesString() {
return Long.toString(number).getBytes(StandardCharsets.ISO_8859_1);
}
Gruss
Bernd
10 years, 6 months
JDK6 Support
by Jason Greene
Is there anyone using undertow on JDK6, and cares that we continue to support it? We are considering dropping it.
--
Jason T. Greene
WildFly Lead / JBoss EAP Platform Architect
JBoss, a division of Red Hat
10 years, 6 months
Re: [undertow-dev] Adding setResponseCookies method to HttpServerExchange?
by arjan tijms
On Thu, Jun 5, 2014 at 10:38 PM, Stuart Douglas <sdouglas(a)redhat.com> wrote:
>
> I could add some other interface+method that makes it more obvious,
> although there would be a very slight performance impact as it means an
> extra allocation (for the adaptor to go from the new interface to the
> wrapper).
Hmmm, it may not be worth it then especially since this is perhaps not
about such a major use case. Some extra documentation somewhere that this
would be the place to do "pre response write" operations would surely help.
The map itself is directly mutable, is there any reason why you would need
>> a whole new map vs just clearing the existing one?
>>
>
To be absolutely sure that nothing else can possibly see the unmodified
cookie. As an external user I don't know which code all over the place does
a call to any of the getResponseCookies methods before I have had a chance
to that do clearing or replacing/modifying. The new map I now set is a sub
class of some map that modifies the cookie immediately in its put() method.
Of course what I conceptually actually would like to do is wrap
HttpServerExchange
so that I could directly intercept its setResponseCookie method.
Since that is rather hard with the current setup (HttpServerExchange is a
final class and a huge one at that) the ability to set your own specialized
map type seems to be the next best thing for this use case.
Kind regards,
Arjan
>
> Stuart
>
>
>> Kind regards,
>> Arjan
>>
>>
>> Even though this primary purpose of this hook is to wrap the
>> response channel, you can also use it to do actions that need to
>> occur just before the response is written, such as modifying cookies.
>>
>> Stuart
>>
>> arjan tijms wrote:
>>
>> Hi,
>>
>> I'm trying to intercept the way that cookies are being written in
>> Undertow. The idea is to do something like can be done with a
>> cookie
>> rewrite rule in Apache (like e.g. add or replace something to
>> the domain
>> attribute of each and every cookie being written).
>>
>> After some hacking on the Undertow code it became clear that
>> HttpServerExchange#__setResonseCookie is the central place where
>>
>> cookies
>> arrive.
>>
>> However, HttpServerExchange is a final class, so can't (easily) be
>> wrapped. If HttpServerExchange only had a setResponseCookies
>> method then
>> handlers could install a special map that does the rewriting,
>> making
>> this a fairly easy task.
>>
>> What do you think? Would it be a good idea to add such a method.
>> or is
>> there an other way to easily do something like this?
>>
>> Kind regards,
>> Arjan Tijms
>>
>> _________________________________________________
>> undertow-dev mailing list
>> undertow-dev(a)lists.jboss.org <mailto:undertow-dev@lists.jboss.org
>> >
>> https://lists.jboss.org/__mailman/listinfo/undertow-dev
>> <https://lists.jboss.org/mailman/listinfo/undertow-dev>
>>
>>
>>
10 years, 6 months
Adding setResponseCookies method to HttpServerExchange?
by arjan tijms
Hi,
I'm trying to intercept the way that cookies are being written in Undertow.
The idea is to do something like can be done with a cookie rewrite rule in
Apache (like e.g. add or replace something to the domain attribute of each
and every cookie being written).
After some hacking on the Undertow code it became clear that
HttpServerExchange#setResonseCookie is the central place where cookies
arrive.
However, HttpServerExchange is a final class, so can't (easily) be wrapped.
If HttpServerExchange only had a setResponseCookies method then handlers
could install a special map that does the rewriting, making this a fairly
easy task.
What do you think? Would it be a good idea to add such a method. or is
there an other way to easily do something like this?
Kind regards,
Arjan Tijms
10 years, 6 months
Date Handler time (optimisation)
by Bernd Eckenfels
Hello,
in Undertow 1.0.1 the DateHandler retrieves System.nanoTime() on each
request and compares it against a deadline to decide if it should also
query wallclock (via System.currentTimeMillis).
I see two possible optimizations here:
If the "Record request start time" option is set, the nanos value
can be read from the exchange.getRequestStartTime and does not need
another query. (Alternatively you can switch the record option off
and make DateHandler write to exchange.setRequestStartTime() to make
the syscall count: the additional time is
available without specifying the RECORD option).
The alternative optimization is about not using the nanos clock for
determining if cached value is stale but directly requesting the
wallclock millis. For one, I think the latency of nanoTime is not much
better (on some systems worse) than System.currentTime (after all, it
is an hotspot intrinsic) and every second both clocks would be asked
(multiple times its a race).
When having the current millis value, you could also check
if actually the next second has started (and avoid the rouding problem
with "nanos + 1000000000".
(And again, if the wallclock time is determined this way, it would make
sense to add it as a field on exchange?)
The code+cache is BTW in two places:
io.undertow.util.DateUtils.addDateHeaderIfRequired(HttpServerExchange)
io.undertow.server.handlers.DateHandler.handleRequest(HttpServerExchange)
BTW: I think the documentation should mention this. Here are some
things which should be included (somewhere):
"If you do not add the DateHandler Undertow might still add a Date:
header if response does not have one and the ALWAYS_SET_DATE
Header option is TRUE or missing. Using "ALWAYS_SET_DATE" is prefered,
as it will use the latest possible time before the response entity is
generated. The name of the option might be missleading, it does not
ansure the header is always overwritten, it only ensures there is one
set if there was not produced by the handlers."
Once the above options are discussed and decided I can provide patches
for the various doc locations.
Bernd
PS: I participated in an experiment* from Aleksey (of JMH fame) and had
a few strange results where currentTime had high latency, on the
other hand there are cases where nanoTime has high latency as
well (see
http://shipilev.net/blog/2014/nanotrusting-nanotime/). I think overall
typical numbers show comparable latencies for both (<20ns). I asked
him, if he can share his experiences.
* https://github.com/shipilev/timers-bench
10 years, 6 months
Nit: MAX_ENTITY_SIZE, Default -1 vs. 0
by Bernd Eckenfels
Hello,
(while researching some details for the pending documentation pull
request I noticed):
SpdyReceiveListener is using:
this.maxEntitySize =
undertowOptions.get(UndertowOptions.MAX_ENTITY_SIZE,
UndertowOptions.DEFAULT_MAX_ENTITY_SIZE);
While HTTPReadListener and AjpReadListener is using:
this.maxEntitySize =
connection.getUndertowOptions().get(UndertowOptions.MAX_ENTITY_SIZE,
0);
The DEFAULT_MAX_ENTITY_SIZE is defined as -1. I think it would be good
to use the constant in HTTP+AjpReadListener (and
HttpServerExchange(ServerConnection)) as well.
I think using -1 as the constant and in all places looks better, but
more backward compatible would be 0. In
HttpServerExchange#maxEntitySize for example it is documented as 0
means unlimited.
The limit is checked here, and all accept 0 and -1 as unlimited:
FixedLengthStreamSourceConduit#checkMaxSize()
AjpServerRequestConduit#soRead()
ChunkedStreamSourceConduit#updateRemainingAllowed()
Gruss
Bernd
10 years, 6 months