Does anyone familiar with Tuckey or Undertow predi...
# box-products
s
Does anyone familiar with Tuckey or Undertow predicates know if there is a way to proxy-pass a subdirectory to an app hosted on another domain? I currently do this with NGINX mapping my
/kb
"directory" to
<http://mydomain.helpjuice.com|mydomain.helpjuice.com>
as described here: https://help.helpjuice.com/en_US/helpjuice-subdir
I'm moving to a container based hosting using the Commandbox base image and would like to leave NGINX out of the stack if possible.
b
@seandaniels If I'm reading that right, I believe an have an example in the docs that does just that
s
Hmm. I scoured the docs. Lemme look again.
b
Copy code
path-prefix('/reports') -> reverse-proxy({'<http://reports1.mydomain.com>','<http://reports2.mydomain.com>'})
So all requests to a file inside the
/reports
folder would round robin between the two domains listed
s
Yeah I tried that. There's more to it than that apparently. I just get a 503 error with that predicate in place
b
Did you enable trace logging to look for clues
I've bumped heads before with Undertow's lax logging in the related classes
Were you sending to an HTTP or HTTPS endpoint?
s
I think because it's a third party host, some extra junk needs to get sent in the back end request. X-Forwarded-For maybe?
https
b
The proxy should add all that
s
I'll try it again, I have not looked with trace logging enabled.
b
It's marked resolved, but I'm confused by the version number listed there 🤔
As a test, can you proxy over HTTP
s
FWIW I'm almost done with a workaround using a ColdBox event & cfhttp to create my own proxy. Sems to be doing the job
b
Yeah, that will work, it's just a bit heavier handed
s
Yeah, I've tried http and it does not work, but I may be able to disable "require https" on the helpjuice side
b
This used to be an issue, but it looks fixed too https://issues.redhat.com/browse/UNDERTOW-240
I'll have to tests again and see if Undertow has ironed out their HTTPS issues they used to have
I recall the proxy working well, but when it had an issue, it had terrible messaging
s
Interesting. I will see if I can get it working with http to rule out that UNDERTOW-201 issue
b
This one's still not resolved 😕
Annoying
s
Yep!
b
Please comment on that ticket and harrass them a bit
👍 1
The Redhat team for Undertow has proven to be exceedinlgly slow in handling some things
Like my pull request from LAST DECEMBER still sitting there 😕
😬 1
I still can't believe they didn't make that work out of the box, and this also shows how annoying and pedantic writing anything in Java is compared to CF, lol
In Java, one doesn't "simply" connect to an SSL endpoint 😆
😂 1
When I first asked about it on the lists, I remember Stuart (lead dev of Undertow) saying, "bUt WhAt If ThE sErVeR rEqUiReS aN sSl ClIeNt CeRt??" eye roll
He made 0% of SSL proxies work because he didn't know how to handle 0.05% of them
s
Oh man. That is a great attitude! Dev of the year
b
Instead of making the other 99.95% wrk
Actually, Stuart isn't that bad.
There's a new project manager of Undertow at RedHat who seems nice, but is never around and never replies to anything on list
And some idiot in their message tracker who comes and argues with me on my tickets about the most nonsensical things
Or-- my favorite-- completes my ticket but not how I asked it to be done and then when I ask why, ignores me. Great times.
😑 1
Anywhoo, somehow that's still sometimes more feedback I get than the Lucee devs .... zing! 💥 🤣 🤣 🤣 🤣
s
Hahahahaha no doubt. But hey ¯\_(ツ)_/¯
b
Sometimes I feel my life boils down to babysitting a bunch of open source projects so I can make my own crap work 🙂
s
OK, this is bizarre. I disabled "require SSL" and used the reverse-proxy predicate action. I no longer get the 503 error, but the page rendered is a default Heroku "There's nothing here, yet" page? So odd. I have no idea where that is coming from.
b
Is the remote service hosted on Heroku?
s
I've no idea, but that's what I'm guessing too.
b
If the original request was
Copy code
<http://original.com/kb/foo|original.com/kb/foo>
and your proxy is pointing to
Copy code
<http://new.com/|new.com/>
then I believe the same URI will be appended so it hits
Copy code
<http://new.com/kb/foo|new.com/kb/foo>
Can you show your rule so I can see it?
Chances are you are doubling up the folder somewhere
The proxy basically just appends the original URI to the proxy URL (unless you do a rewrite first)
s
Yeah, that's what it should do. My config rule looks like this:
path-prefix('/kb') -> reverse-proxy({'<http://dealstream.helpjuice.com>'})
b
If I try to hit that over HTTP it redirects back to HTTP
s
so
/kb/contact-us
should pull
<http://dealstream.helpjuice.com/contact-us>
I was wondering that
b
so
/kb/contact-us
should pull
<http://dealstream.helpjuice.com/contact-us>
Wait, wait-- do you DO want the original URI to change
s
oh! yes
b
As I said above, that's not how it works-- the full original URI is pasted on the proxy server
s
Right, I misunderstood your previous comment
b
So you can do a rewrite on this, but I didn't realize you needed that
s
OK. So yeah, that's not gonna work then.
b
no, it will work
As I said, you just need to rewrite the requests before proxying
s
OK. Cool. So I need the predicate AND a rewrite
b
you need the predicate and two handlers 🙂
s
Not sure what you mean.
b
You can do it one of two ways. The latter is the most concise, but the former may be more readable
A predicate is an if statement-- a condition which is try or false.
path-prefix('/kb')
is your predicate
A handler is an action that is performed on the request
s
Oh, are you saying you can chain the actions in the predicate rule?
b
reverse-proxy(...)
is currently your only handler
s
Gotcha
b
But you can have an many handlers that run as you like once a predicate is met
So, back to the two approaches
s
Cool cool cool
b
You'll probably want to switch to a regex handler so you can do capture groups to carve up the URI. Path-prefix is handy, but doesn't allow you to just use part of it
👍 1
So I'd change your predicate so something like
Copy code
regex( '^/kb/(.*)$' )
And then -- I don't care much for the syntax when doing this in
server.json
but you can have two handlers like this example shows
Copy code
regex('(.*).css') -> { rewrite('${1}.xcss'); set(attribute='%{o,rewritten}', value=true) }
Watch out-- undertow is a little picky about those semi colons-- I have tickets in for that
s
ok, I think I get it. trying
b
So, that ends us with something like this
Copy code
regex( '^/kb/(.*)$' ) -> { rewrite('\${1}'); reverse-proxy({'<http://dealstream.helpjuice.com>'}) }
👍 1
The
\
is necessary to escape the
${1}
in your
server.json
since Undertow uses the same syntax as CommandBox's system setting expansions for it's predicate context values
So we want CommandBox to ignore that and pass the literal string to Undertow, which will replace it with the first capture group from the regex
CommandBox's
--trace
logging will show you what the request gets rewritten to prior to proxying it so you can confirm
s
Thanks for that clarification about escaping ${1}, that confused me 🙂
m
0
b
And-- the benefit of moving rules out to an external text file is you can format it like so in the text file (plus you don't need to escape anything for JSON OR for system settings!)
Copy code
regex( '^/kb/(.*)$' ) -> {
  rewrite('\${1}');
  reverse-proxy({'<http://dealstream.helpjuice.com>'})
}
I really like the readability of an external text file for complex rules, it's just not as quick and self-contained as putting them in the JSON
s
If I put them in a external file, how do I reference that in server.json?
s
I'm getting an error when I launch the container
parse error: Invalid escape at line 10, column 111
<- that;s the line with the rule
b
In addition to the
rules
array there is a
rulesFile
property which can contain a comma-delimited list of file globbing patterns of files to use
Can you show the context of the error?
Is that coming from CommandBox when parsing the
server.json
or undertow when parsing the predicate?
The JSON file may require your
\
to be escaped again for the JSON
This is where it gets really annoying to put this stuff in JSON, lol
s
Pretty sure it's coming from CommandBox. When I fire up the container, I get two lines of log before it dies:
Copy code
2023-01-12 14:38:13 Set verboseErrors = true
2023-01-12 14:38:14 parse error: Invalid escape at line 10, column 111
b
Then do this
Copy code
regex( '^/kb/(.*)$' ) -> { rewrite('\\${1}'); reverse-proxy({'<http://dealstream.helpjuice.com>'}) }
😂 1
Is this in Docker?
s
yep
b
That errror is probably coming from
jq
whcih is why I didn't recognize it
Our Docker iamges use
jq
to screw around with the JSON
One thing I hate is trying to guess how many freaking backslashes to use, lol
s
ok, that extra escape looks like it fixed that issue
b
But I think you need • one backslash so CommandBox ignores
${1}
• One additional backslash so the JSON parser ignore the original
\
What gets even more fun is if you try to set this rule from the CLI!
Then you wind up typing something like
Copy code
server set web.rules[1]="regex( '^/kb/(.*)$' ) -> { rewrite('\\\\${1}'); reverse-proxy({'<http://dealstream.helpjuice.com>'}) } "
Because then you have to • double up the
\\
for the CLI parser!
s
Hm. So now I'm getting an nginx 400 bad request error. with the rule:
Copy code
regex( '^/kb/(.*)$' ) -> { rewrite('\\${1}'); reverse-proxy({'<http://dealstream.helpjuice.com>'}) }
b
I understand now what does the trace logging show you?
I assume the 400 is coming from the remote Heroku-hosted service
So the first thing you check is if the rewrite did what you wanted
You may be missing a slash or something
s
in the docker context
Well, I'll spare you the lecture about how Docker makes EVERYTHING more complicated 🙂
😂 1
There's two ways you can do it
s
ha. I'm in box in the docker terminal
can I just restart the server? stop, then start with trace?
b
Set it in the
server.json
Copy code
server set trace=true
or via env var on your container
Copy code
box_server_trace=true
No, you can't restart the server within a docker container
Docker doesn't allow that because the server process basically IS the container
s
Right
I guess 🤣
I'm pretty newb vis a vis Docker so this whole thing is real fun
b
I hate Docker for local dev-- everything that should be fast and easy gets harder and takes longer. I love it on my prod deploys though
Ortus switched to Docker Swarm on our stage and prod servers years ago and never looked back
👍 1
But for my local work, it's just
server start
all the way :_)
s
That's my goal
Good to know. I'm sure I will go back to that once I get prod going
whoa ok, lotsa log 🤣
b
yep
What I do is • let the server start • hit enter a couple times in the console where I'm tailing the log file • hit a single request • go back and inspect just the new lines
Otherwise, it's impossible to follow
👍 1
--debug
mode will give you some data, but I don't recall if it will have everything you want in the server rules department
s
I think this is relevant:
Copy code
2023-01-12 14:51:29 [DEBUG] runwar.context: requested: '<http://localhost:8080/kb/contact-us>'
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Path suffix [secrets.json] DOES NOT MATCH input [/kb/contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Predicate [path-suffix( 'secrets.json' )] resolved to false for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Regex pattern [^/kb/(.*)$] MATCHES input [/kb/contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Storing regex match group [0] as [/kb/contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Storing regex match group [1] as [contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Predicate [regex( pattern='^/kb/(.*)$', value='%{RELATIVE_PATH}', full-match='false', case-sensitive='false' )] resolved to true. Next handler is [PredicatesHandler with 2 predicates] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Executing handler [rewrite( '${1}' )] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [DEBUG] io.undertow.predicate: Request rewritten to [contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:51:29 [TRACE] io.undertow.predicate: Executing handler [reverse-proxy( '<http://dealstream.helpjuice.com>' )] for HttpServerExchange{ GET contact-us}.
2023-01-12 14:51:29 [DEBUG] io.undertow.server.handlers.proxy: Sending request ClientRequest{path='contact-us', method=GET, protocol=HTTP/1.1} to target <http://dealstream.helpjuice.com/50.16.128.128:80|dealstream.helpjuice.com/50.16.128.128:80> for exchange HttpServerExchange{ GET contact-us}
2023-01-12 14:51:29 [DEBUG] io.undertow.server.handlers.proxy: Sent request ClientRequest{path='contact-us', method=GET, protocol=HTTP/1.1} to target 172.29.0.1 for exchange HttpServerExchange{ GET contact-us}
b
Yeah, I think you need to add the slash
s
Copy code
HttpServerExchange{ GET contact-us}
shold probably be
Copy code
HttpServerExchange{ GET /contact-us}
right
b
Copy code
regex( '^/kb/(.*)$' ) -> { rewrite('/\\${1}'); reverse-proxy({'<http://dealstream.helpjuice.com>'}) }
yep
I think I have a ticket for this eye roll
undertow does a good job of dealing with leading slashes, but not everywhere
Ah yes-- only fixed on the next "major" version of Undertow 2.3
Which means it will be years before CommandBox ever gets the fix 😢
Oh wait-- it's in 2.2.21 as well!
What version of CommandBox are you on?
Looks like they JUST fixed this
s
5.6.1+00618
b
Boom
If you were on 5.7 like you shoyld be, yoiu'[d have the fix 😉
Well, in theory, I haven't tested to see if they fixed it right, lol
But the latest CommandBox shipped with Undertow 2.2.21
Anyway, just add that slash and see what it gets us
s
Another Docker thing I haven't grokked. I'm using the
FROM ortussolutions/commandbox:lucee-light
base image - shouldn't that always get the latest? Do I need to destroy my containers and rebuild them to get the latest
b
I want to say yes, but I'm not really sure how Docker handles that
s
So yeah, I added the slash ad now I get the heroku page again. Checking the logs now
b
I don't think
docker build
always actively pulls the latest
I think you have to periodically run
Copy code
docker pull ...
or use
Copy code
docker build no-cache
Otherwise, Docker will use whatever local copy of that image you have
s
Copy code
2023-01-12 14:59:36 [TRACE] io.undertow.predicate: Regex pattern [^/kb/(.*)$] MATCHES input [/kb/contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:59:36 [TRACE] io.undertow.predicate: Storing regex match group [0] as [/kb/contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:59:36 [TRACE] io.undertow.predicate: Storing regex match group [1] as [contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:59:36 [TRACE] io.undertow.predicate: Predicate [regex( pattern='^/kb/(.*)$', value='%{RELATIVE_PATH}', full-match='false', case-sensitive='false' )] resolved to true. Next handler is [PredicatesHandler with 2 predicates] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:59:36 [TRACE] io.undertow.predicate: Executing handler [rewrite( '/${1}' )] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:59:36 [DEBUG] io.undertow.predicate: Request rewritten to [/contact-us] for HttpServerExchange{ GET /kb/contact-us}.
2023-01-12 14:59:36 [TRACE] io.undertow.predicate: Executing handler [reverse-proxy( '<http://dealstream.helpjuice.com>' )] for HttpServerExchange{ GET /contact-us}.
2023-01-12 14:59:36 [DEBUG] io.undertow.server.handlers.proxy: Sending request ClientRequest{path='/contact-us', method=GET, protocol=HTTP/1.1} to target <http://dealstream.helpjuice.com/50.16.128.128:80|dealstream.helpjuice.com/50.16.128.128:80> for exchange HttpServerExchange{ GET /contact-us}
2023-01-12 14:59:36 [DEBUG] io.undertow.server.handlers.proxy: Sent request ClientRequest{path='/contact-us', method=GET, protocol=HTTP/1.1} to target 172.29.0.1 for exchange HttpServerExchange{ GET /contact-us}
b
Out of curiosity, is
<http://dealstream.helpjuice.com/contact-us>
a real example or a fake one? Because when I hit it • it still redirects me to HTTPS • I get a "Couldn't find what you're looking for?" page
s
hm. I think so? it redirects me too. I thought that might be a browser cache issue (Chrome gives me the 307 status)
b
I see a
*strict-transport-security:* max-age=0
header. If that was set earlier to something other than 0, our browsers probably remember it
👍 1
s
It's strange, because using cfhttp to pull from the http version worked, so I assumed it was not redirecting to https. But maybe it was, I forget how cfhttp handles redirects. I guess it follows them unless you specify not to
b
HSTS is a tough thing to clear from browser cache, by design
s
yep
b
Does Heroku have an access log to show the incoming requests?
Everything looks correct from your logs above
s
Not that I have access to. Since it's a third party thing
Yep agreed
b
Dang, hard to get eyes on it then outside of using a packet sniffer or something
Could be something like Heroku doesn't like the user agent that's coming from Undertow so it blocks it?
Hard to say
s
So it must be something to do with HelpJuice still requiring https via that
*strict-transport-security:* max-age=0
header
b
Undertow doesn't obey that header BTW. That's just a browser thing
s
but that's a browser thing right? So yeah
b
max-age=0
just turns it off, but I assume whatever setting you changed previously had a non-zero setting
s
Ah, right. But you never visited that domain with it set to something else before right? Not sure why your browser would still be redirecting, unless it's still configured to redirect
Hm. I just noticed this in the log during the proxy request:
Copy code
2023-01-12 14:59:36 [TRACE] io.undertow.client.request: Processing header 'Host'
2023-01-12 14:59:36 [TRACE] io.undertow.client.request: Processing header value 'localhost:8080'
2023-01-12 14:59:36 [TRACE] io.undertow.client.request: Processing header 'X-Forwarded-Host'
2023-01-12 14:59:36 [TRACE] io.undertow.client.request: Processing header value 'localhost'
2
b
That's probably just coming from the proxy since you have trace turned on
When I hit that site over HTTP in FireFix (a new browser), it still redirects to HTTPS. I'm not sure if that's related, but it's interesting.
s
Right, but also there's this:
Copy code
2023-01-12 14:59:36 [TRACE] io.undertow.client.request: Processing header 'X-Forwarded-For'
2023-01-12 14:59:36 [TRACE] io.undertow.client.request: Processing header value '172.29.0.1'
And the HelpJuice docs specifically say the X-Forwarded-For header needs to be set to
<http://dealstream.helpjuice.com|dealstream.helpjuice.com>
b
I assume that's it following a redirect
Those log messages are just coming from some underlying classes in undertow that deal with headers https://github.com/undertow-io/undertow/blob/master/core/src/main/java/io/undertow/client/http/HttpRequestConduit.java#L176
There's all sorts of interesting logs that popup when you enable trace 🙂
s
So, if I hit the IP that
<http://dealstream.helpjuice.com|dealstream.helpjuice.com>
resolves to, I get the exact Heroku page I'm seeing: http://50.16.128.128/contact-us
Something on their end obviously uses the host to determine which app to run. And I think something about our proxy is not fulfilling what it needs to determine which app to field the request.
From their page on how to set this up with Nginx:
Copy code
If you're rewriting the requests, make sure that you're also changing the value of the Origin HTTP header to the account's subdomain in HJ: <https://yourAccount.helpjuice.com>.
```proxy_set_header Host yourAccount.helpjuice.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For yourAccount.helpjuice.com;```
The undertow proxy request is setting X-Forwarded-For to 172.29.0.1, which I'm guessing is the IP of my Docker container
b
Yeah, but that's not the same as the host
It's really hard to tell what's going on without better logging
s
yep.
b
I need to see the response headers heroku is sending back when it redriects
s
I think for some reason HelpJuice requires both the Host and X-Forwarded-For headers to contain that value to load the correct app. Dumb? But they are very clear in their docs this method won't work without that value in X-Forwarded-For
b
Yeah, that doesn't make any sense--
X-Forwarded-For
is the IP/host of the client
You could try setting that response header, but I'm not sure it will get used, or won't get overwritten
I don't quite understand what's happening there to understand if Undertow is doing the proxy wrong or if Heroku is demanding a non-standard proxy header to be set
👍 1
s
Interesting idea. Can that be done with a predicate handler?
b
Everything can be done with a predicate handler, lol
But I think that will only affect the current request undertow is processing-- not the HTTP request made to the proxied server
s
Right
Ah well, I'm tapped for time now. Very much appreciate the help here. For now I guess it's the heavy handed approach 🤣
b
Yeah, I'd really like to find why this doesn't work, but I'm having a hard time figuring out where Undertow is handling redirects
s
btw I confirmed adding
set(attribute='%{o,X-Forwarded-For}', value='<http://dealstream.helpjuice.com|dealstream.helpjuice.com>');
to the handler does not change the value from the 172 ip the proxy request sends
👍 1
b
Nothing is simple in this code base-- it's a mess of callbacks and interfaces spread all over
s
heh
I'm opening a support ticket with HelpJuice to see if they can help me figure out what's going on on their end. We'll see. I've never dealt with them before.
b
👍
Recreating on my end so I can test too
I've compiled a custom version of Undertow many times with my own additional logging to figure out what the #$%^&* it's doing on many occasions
s
That's some five dimensional programming action!
b
Looking further, I can see there's a lot more trace logging that was showing in the console than you relayed here...
s
oh yeah for sure. I was trying to be helpful 🤣
b
I no longer think there's a redirect at play-- I think Heroku is rejecting the requests with a 404 right away due to its oddball header requirement
s
That's what I'm assuming too. I mentioned that in my ticket. Like, why do they need that.
s
That said, inspecting the response via my cfhttp call with redirect=false, it does appear HelpJuice is also still force-redirecting to https
b
while buklding the proxy request
s
don't know how undertow would handle that
b
I don't think the HTTPS is at play right now
I think it's likely another issue, but I think the 404 is happening from having the wrong headers first
👍 1
What's interesting is looking at the Undertow code reveals a
reuseXForwarded
variable which does this
Copy code
* @param reuseXForwarded should any existing X-Forwarded-For header be used or should it be overwritten. should any existing X-Forwarded-For header be used or should it be overwritten.
That actually sound like what you want, but it defaults to false
s
Huh. Interesting. So if we were able to change that to true, maybe my set(attribute='%{o,X-Forwarded-For}', value='dealstream.helpjuice.com'); would fix it
b
We're not directly creating the Java classes however, we're using the build defined here https://undertow.io/undertow-docs/undertow-docs-2.0.0/#reverse-proxy-handler
Which doesn't appear to expose that flag in the underlying class 😕
It's not uncommon to have some of the predicate language builders that don't offer all the possible settings allowed in the underlying class they create
s
Useful! 🤣
d
Respect to you guys for all this fun!
😂 2
b
I'm sure it's not commonly-used, but I suspect someone with a scenario similar to you is why that setting was first added 🙂
Here's the cool thing though-- it's possible add your own contributions to the predicate language. We could write our own handlerbuilderclass like the one above, but pass
true
(or make it configurable). It would need to be compiled into a jar and added to your
libDirs
. CommandBox actually has a few custom predicates and handlers built in that I wrote such as
cf-admin()
and
block-external()
s
Whoa. Cool.
b
I could also submit a pull request to Undertow to add a setting in the predicate language to control that boolean, but I'm a little annoyed at their lack of responsiveness to my last few pulls
Plus, they would probaly classify it as a "feature" and only add it to 2.3 which we won't be able to use until Lucee/Adobe switch over from javax to the new jakarta namespace, an important move neither CF engine has expressed any interesting in doing
s
OK, so then the question becomes, is all that work to use this versus my cfml-based approach worth it? Sounds like a fun project for sure, but heh
b
Um, probably not, but it is fun 🙂
I mean, it would probably only take a few minutes to cook up a jar that did that, but it's a bit messy of a workaroud for what you need. It's just cool we have the ability to add anything we want to the predicate language
I have a meeting I need to jump into now anyway... duty calls
s
Thanks again my man
That was highly educational 👍🏻
b
Poking at this during my call, if I turn on
rewrite-host-header
then I get an HTTPS redirect, which is expected from the browser's behavior
Copy code
reverse-proxy(hosts={'<http://dealstream.helpjuice.com>'},rewrite-host-header=true)
If you can figure out how to actually disable HTTP for your docs site, that may finally work
Even when I run my localhost site on SSL and the following headers are sent to Heroku (over HTTP)
Copy code
X-Forwarded-Proto=https
X-Forwarded-Port=443
it still tries to redirect. But it's up to the remote server to decide if it will allow the upstream to be HTTPS or if the proxy must use HTTPS as well
I did compile a custom handler which sets the reuse x-forwarded flag, and while it adds this header to the proxied request
Copy code
X-Forwarded-For=<http://dealstream.helpjuice.com|dealstream.helpjuice.com>,127.0.0.1
it doesn't appear to do what we need.
The rewrite-host-header flag appeared to actually be what we needed for Heroku's server to recognize the hostname coming in, but that just leaves the SSL redirect an issue
FWIW, it also redirects to
Copy code
<https://127.0.0.1/contact-us>
not
Copy code
<https://127.0.0.1/kb/contact-us>
(which leads to a CommandBox 404) but that's to be expected as the proxied server knows nothing of our little
kb
prefix. I also had to run my local test site on ports 80/443 or the proxy redirects got confused, lol. I've run into that before with SSL redirects.
s
Hopefully I'll be able to at least get them to turn off that redirect. We'll see.
I vaguely recall them telling me to update my nginx proxy rule to use https because they were no longer supporting http traffic. Ugh
b
I mean, I'm not surprised
which makes it even more annoying that the Undertow devs chose to sit on this for years
s
yep, exactly
b
my.jar
server.json
Copy code
{
  "app": {
    "libDirs": "lib"
  },
  "web": {
    "http": {
      "port": "80"
    },
    "rules": [
      "regex( '^/kb/(.*)$' ) -> { rewrite('/\\${1}'); reverse-proxy-ssl(hosts={'<https://dealstream.helpjuice.com>'}, rewrite-host-header=true) } "
    ],
    "SSL": {
      "enable": "true",
      "port": "443"
    }
  }
}
@seandaniels That works for me, Put the jar in the lib folder
I can hit
Copy code
<https://127.0.0.1/kb/228854-searching-listings/1141270-how-do-i-search-for-listings-on-a-desktop-or-laptop-computer>
local SSL probably isn't necessary, I just had it in there from testing
The Java code is below with the one line that really changed (other than some imports and a try/catch) is this
Copy code
loadBalancingProxyClient.addHost(url, new UndertowXnioSsl( Xnio.getInstance(), OptionMap.builder().getMap() ) );
which creates a default SSL context
ProxyHandlerBuilder.java
I compiled it with
Copy code
javac -cp C:\Users\Brad\.CommandBox\lib\runwar-4.7.19-SNAPSHOT.jar  -d C:\Users\Brad\Desktop\sandbox\proxy\bin\ C:\Users\Brad\Desktop\sandbox\proxy\src\fun\test\ProxyHandlerBuilder.java
C:\Users\Brad\Desktop\sandbox\proxy\bin>jar --create --file my.jar fun\test\ProxyHandlerBuilder$Wrapper.class fun\test\ProxyHandlerBuilder.class
and then copied in the
META-INF/resources
folder to the jar
I don't know if any custom SSL settings need to be set (all the possible ones are here: https://docs.jboss.org/xnio/3.1/api/org/xnio/Options.html ) but a default context seems to work out of the box
@seandaniels
I might just include that handler directly in CommandBox in the next version
❤️ 1
I've already been wanting to create a
path-prefix-nocase()
predicate since
path-prefix()
is case sensitive which totally makes it worthless for security checks on Windows.
Same with
regex()
-- I'd like to create a
regex-nocase()
which defaults
case-sensitive=true
since it's a pain to always have to include that (and then you're forced to use named params)
s
This is amazing dude. You've gone above and beyond! Sorry to divert your day 🤣
I will drop this stuff in when I'm back at my desk!
b
No worries, I'd wanted to find a workaround for that stupid SSL issue for a while anyway.
👍 1