Sorry, bad example.

I send ws://<host>:<port>/gateway/pnda/pndaconsole/
socket.io/?EIO=3&transport=websocket

Knox sends /socket.io/

That yields a 400 error, Knox throws
org.eclipse.jetty.websocket.api.UpgradeException: Didn't switch protocols


On Mon, Jun 18, 2018 at 6:49 PM, T Smith <ailurop...@gmail.com> wrote:

> Hi Sandeep,
>
> Back to fighting with this. Through some nginx debugging on my backend
> I've come to the conclusion that Knox isn't sending the query parameters on
> to the backend, regardless of what rewrite rules I specify.
>
> I.e. I send /gateway/pnda/pndaconsole/socket.io/?EIO=3&
> transport=polling&t=MDGlYhd
> <http://34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io/?EIO=3&transport=polling&t=MDGlYhd>
>
> Knox sends /socket.io/
> <http://34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io/?EIO=3&transport=polling&t=MDGlYhd>
>
> This yields a 400 error, and Knox drops the websocket to the backend. What
> was confusing me was the 101 in the browser, but I see now that Knox is
> terminating the connection with the browser on one side and opening another
> connection with the backend on the other.
>
> I see this https://git-wip-us.apache.org/repos/asf?p=knox.git;h=98a08fc
> but I'm wondering if this code needs further work to support query
> parameters? What do you think?
>
> Thanks in advance!
>
> /ailuropod4
>
> On Thu, May 17, 2018 at 8:57 AM, T Smith <ailurop...@gmail.com> wrote:
>
>> Hi Sandeep,
>>
>> Looking at my nginx server, it never sees the transport=websocket ws://
>> protocol request, but it does see a http request for / at the corresponding
>> time, so I think perhaps the root problem here is in that rewrite, as you
>> mention. By the way, the reason for ws:// and not wss:// is I switched off
>> TLS to remove another potential source of issue, so it's all plain http. I
>> saw the same behaviour over https.
>>
>> My services, now, look like this -
>>
>>     <route path="/pndaconsole/socket.io">
>>       <rewrite apply="PNDACONSOLE/pndaconsole/inbound/socket"
>> to="request.url"/>
>>     </route>
>>
>>     <route path="/pndaconsole/metrics">
>>       <rewrite apply="PNDACONSOLE/pndaconsole/inbound/metrics"
>> to="request.url"/>
>>     </route>
>>
>>     <route path="/pndaconsole/">
>>       <rewrite apply="PNDACONSOLE/pndaconsole/inbound/root"
>> to="request.url"/>
>>     </route>
>>
>>     <route path="/pndaconsole/**">
>>       <rewrite apply="PNDACONSOLE/pndaconsole/inbound/path"
>> to="request.url"/>
>>       <rewrite apply="PNDACONSOLE/pndaconsole/outbound/app"
>> to="response.body"/>
>>     </route>
>>
>> My inbound rewrites, now, look like this -
>>
>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/root"
>> pattern="*://*:*/**/pndaconsole/">
>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/"/>
>>     </rule>
>>
>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/socket"
>> pattern="*://*:*/**/pndaconsole/socket.io/?{**}
>> <http://socket.io/?%7B**%7D>">
>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/socket.io/?{**}
>> <http://socket.io/?%7B**%7D>"/>
>>     </rule>
>>
>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/path"
>> pattern="*://*:*/**/pndaconsole/{**}">
>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/{**}"/>
>>     </rule>
>>
>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/metrics"
>> pattern="*://*:*/**/pndaconsole/metrics/?{**}">
>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/metrics/?{**}"/>
>>     </rule>
>>
>> The ws://...transport=websocket requests are rewritten as /, so I tried
>> adding an entry in my topology for WEBSOCKET and an additional inbound rule
>> like this -
>>
>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/socket"
>> pattern="ws://*:*/**/pndaconsole/socket.io/?{**}
>> <http://socket.io/?%7B**%7D>">
>>         <rewrite template="{$serviceUrl[WEBSSOCKET]}/socket.io/?{**}
>> <http://socket.io/?%7B**%7D>"/>
>>     </rule>
>>
>> Where the topology entry is the same as PNDACONSOLE except it uses the
>> ws:// protocol specifier. This didn't work at all, and in fact at that
>> point, nothing got through and everything fell through to the default
>> rewrite rule.
>>
>> I've attached the gateway log with debug turned on everywhere (tarballed
>> as it's huge).
>>
>> I guess what I'm missing is a clear idea of what I'm supposed to do in
>> the service/rewrite rules to deal with the websockets request which will
>> arrive with a different protocol specifier and a different query parameter.
>> Should I explicitly map those through to the back end, or is this something
>> Knox handles internally?
>>
>> Any insight into this appreciated, it seems very close to working, and in
>> fact socket.io does it's usual fallback so it is functional after a
>> fashion but it seems like this should fully work given what I see with
>> Zeppelin.
>>
>>
>> Cheers,
>> /ailuropod4
>>
>>
>> On Sun, May 13, 2018 at 3:22 PM, Sandeep Moré <moresand...@gmail.com>
>> wrote:
>>
>>> Hello ailuropod4
>>>
>>> You should not have to reroute to a different host port, this should
>>> work.
>>>
>>> Looking at the responses, it looks like protocol switching happens at
>>> the Knox end, between browser and Knox (going by the url ws://
>>> 34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io/?
>>> EIO=3&transport=websocket&sid=n_JBdgXCw_sZL-Q5AAOW) but it should have
>>> been wss:// wonder why this is ws://.
>>>
>>> Also, can you include seperate "ws" rules for your service, similar to
>>> Zeppelin.
>>> Also, make sure you have, inbound routes in service.xml for e.g.
>>>
>>>   <routes>
>>>     <route path="/zeppelin/ws">
>>>       <rewrite apply="ZEPPELINWS/zeppelin/ws/inbound" to="request.url"/>
>>>     </route>
>>>
>>>     <route path="/zeppelin/ws**">
>>>       <rewrite apply="ZEPPELINWS/zeppelin/inbound" to="request.url"/>
>>>     </route>
>>>   </routes>
>>>
>>> and then reference it in rewrite.xml.
>>>
>>> Looking at the error, it looks like the issue is not with rewrite rules
>>> but with the connection between Knox and the backend.
>>> We can see that Knox is initiating an upgrade request but then for some
>>> reason the backend service is closing/refusing it.
>>> Can you turn up the logging in Knox to Debug and share it if you can
>>> (this should atleast tell us whether rewrite rules are working).
>>>
>>> Also, do you see any errors at the backend service ? it woud be good to
>>> know what the backend is seeing and reasons for it to refuse the upgrade
>>> and also the error code
>>> Unfortunately the error code is gobbled up somewhere in the process.
>>>
>>> Best,
>>> Sandeep
>>>
>>> On Sat, May 12, 2018 at 3:16 AM, T Smith <ailurop...@gmail.com> wrote:
>>>
>>>> And if it helps, the stack trace as a result of this from Knox follows.
>>>>
>>>> Can I match a url containing &transport=websocket in one of the query
>>>> parameters and map it through to a service defined as ws:// in the
>>>> topology? At the moment, as above, everything is sent to a http://
>>>> service, maybe this is the crux of the problem?
>>>>
>>>> 2018-05-12 07:09:47,361 ERROR gateway.websockets
>>>> (ProxyWebSocketAdapter.java:cleanupOnError(171)) - Error:
>>>> org.eclipse.jetty.websocket.api.UpgradeException: Didn't switch
>>>> protocols
>>>> 2018-05-12 07:09:47,362 ERROR gateway.websockets
>>>> (ProxyWebSocketAdapter.java:onWebSocketConnect(105)) - Unable to
>>>> connect to websocket server: java.io.IOException: Connect failure
>>>> java.io.IOException: Connect failure
>>>>         at org.eclipse.jetty.websocket.jsr356.ClientContainer.connect(C
>>>> lientContainer.java:157)
>>>>         at org.eclipse.jetty.websocket.jsr356.ClientContainer.connectTo
>>>> Server(ClientContainer.java:180)
>>>>         at org.apache.knox.gateway.websockets.ProxyWebSocketAdapter.onW
>>>> ebSocketConnect(ProxyWebSocketAdapter.java:97)
>>>>         at org.eclipse.jetty.websocket.common.events.JettyListenerEvent
>>>> Driver.onConnect(JettyListenerEventDriver.java:87)
>>>>         at org.eclipse.jetty.websocket.common.events.AbstractEventDrive
>>>> r.openSession(AbstractEventDriver.java:227)
>>>>         at org.eclipse.jetty.websocket.common.WebSocketSession.open(Web
>>>> SocketSession.java:421)
>>>>         at org.eclipse.jetty.websocket.server.WebSocketServerConnection
>>>> .onOpen(WebSocketServerConnection.java:72)
>>>>         at org.eclipse.jetty.io.AbstractEndPoint.upgrade(AbstractEndPoi
>>>> nt.java:185)
>>>>         at org.eclipse.jetty.server.HttpConnection.completed(HttpConnec
>>>> tion.java:345)
>>>>         at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java
>>>> :436)
>>>>         at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConne
>>>> ction.java:257)
>>>>         at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnec
>>>> tion.java:544)
>>>>         at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(Queued
>>>> ThreadPool.java:635)
>>>>         at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedT
>>>> hreadPool.java:555)
>>>>         at java.lang.Thread.run(Thread.java:748)
>>>> Caused by: org.eclipse.jetty.websocket.api.UpgradeException: Didn't
>>>> switch protocols
>>>>         at org.eclipse.jetty.websocket.client.io.UpgradeConnection.vali
>>>> dateResponse(UpgradeConnection.java:314)
>>>>         at org.eclipse.jetty.websocket.client.io.UpgradeConnection.read
>>>> (UpgradeConnection.java:241)
>>>>         at org.eclipse.jetty.websocket.client.io.UpgradeConnection.onFi
>>>> llable(UpgradeConnection.java:163)
>>>>         ... 4 more
>>>> 2018-05-12 07:09:47,373 WARN  websockets.ProxyWebSocketAdapter
>>>> (AbstractEventDriver.java:unhandled(245)) - Unhandled Error (closing
>>>> connection)
>>>> org.eclipse.jetty.io.RuntimeIOException: java.io.IOException: Connect
>>>> failure
>>>>         at org.apache.knox.gateway.websockets.ProxyWebSocketAdapter.onW
>>>> ebSocketConnect(ProxyWebSocketAdapter.java:106)
>>>>         at org.eclipse.jetty.websocket.common.events.JettyListenerEvent
>>>> Driver.onConnect(JettyListenerEventDriver.java:87)
>>>>         at org.eclipse.jetty.websocket.common.events.AbstractEventDrive
>>>> r.openSession(AbstractEventDriver.java:227)
>>>>         at org.eclipse.jetty.websocket.common.WebSocketSession.open(Web
>>>> SocketSession.java:421)
>>>>         at org.eclipse.jetty.websocket.server.WebSocketServerConnection
>>>> .onOpen(WebSocketServerConnection.java:72)
>>>>         at org.eclipse.jetty.io.AbstractEndPoint.upgrade(AbstractEndPoi
>>>> nt.java:185)
>>>>         at org.eclipse.jetty.server.HttpConnection.completed(HttpConnec
>>>> tion.java:345)
>>>>         at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java
>>>> :436)
>>>>         at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConne
>>>> ction.java:257)
>>>>         at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnec
>>>> tion.java:544)
>>>>         at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(Queued
>>>> ThreadPool.java:635)
>>>>         at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedT
>>>> hreadPool.java:555)
>>>>         at java.lang.Thread.run(Thread.java:748)
>>>> Caused by: java.io.IOException: Connect failure
>>>>         at org.eclipse.jetty.websocket.jsr356.ClientContainer.connect(C
>>>> lientContainer.java:157)
>>>>         at org.eclipse.jetty.websocket.jsr356.ClientContainer.connectTo
>>>> Server(ClientContainer.java:180)
>>>>         at org.apache.knox.gateway.websockets.ProxyWebSocketAdapter.onW
>>>> ebSocketConnect(ProxyWebSocketAdapter.java:97)
>>>>         ... 12 more
>>>> Caused by: org.eclipse.jetty.websocket.api.UpgradeException: Didn't
>>>> switch protocols
>>>>         at org.eclipse.jetty.websocket.client.io.UpgradeConnection.vali
>>>> dateResponse(UpgradeConnection.java:314)
>>>>         at org.eclipse.jetty.websocket.client.io.UpgradeConnection.read
>>>> (UpgradeConnection.java:241)
>>>>         at org.eclipse.jetty.websocket.client.io.UpgradeConnection.onFi
>>>> llable(UpgradeConnection.java:163)
>>>>         ... 4 more
>>>>
>>>>
>>>> On Fri, May 11, 2018 at 9:04 PM, T Smith <ailurop...@gmail.com> wrote:
>>>>
>>>>> Sorry, the other question was version. I'm using 1.0.0.
>>>>>
>>>>> On Fri, May 11, 2018 at 9:03 PM, T Smith <ailurop...@gmail.com> wrote:
>>>>>
>>>>>> Hi Sandeep,
>>>>>>
>>>>>> Here's what's happening -
>>>>>>
>>>>>>
>>>>>>    1. Request URL:
>>>>>>    http://34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io
>>>>>>    /?EIO=3&transport=polling&t=MDGlYhd
>>>>>>    
>>>>>> <http://34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io/?EIO=3&transport=polling&t=MDGlYhd>
>>>>>>    2. Request Method:
>>>>>>    GET
>>>>>>    3. Status Code:
>>>>>>    200 OK
>>>>>>
>>>>>>
>>>>>>    1. Request URL:
>>>>>>    ws://34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io/?
>>>>>>    EIO=3&transport=websocket&sid=n_JBdgXCw_sZL-Q5AAOW
>>>>>>    
>>>>>> <http://34.244.121.78:8443/gateway/pnda/pndaconsole/socket.io/?EIO=3&transport=websocket&sid=n_JBdgXCw_sZL-Q5AAOW>
>>>>>>    2. Request Method:
>>>>>>    GET
>>>>>>    3. Status Code:
>>>>>>    101 Switching Protocols
>>>>>>
>>>>>> So far, so good. But, the next couple of requests fail, with 400 or
>>>>>> 500 range errors, and the gateway log complains about protocol errors. I
>>>>>> can supply these if you need them, I'm trying to be concise here to get 
>>>>>> the
>>>>>> big picture across.
>>>>>>
>>>>>> Looking at tcpdump, what's happening is that ws:// request is being
>>>>>> nerfed to a GET /, which on my backend happens to resolve to a nice front
>>>>>> page of HTML. Websockets obviously panics as this isn't what it expected,
>>>>>> and then the whole process repeats. On my backend, /socket.io is
>>>>>> routed to the socket endpoint, whereas / isn't. So, my theory is that if 
>>>>>> I
>>>>>> can somehow convince Knox to send out the ws:// request with the correct
>>>>>> path including /socket.io, it might work.
>>>>>>
>>>>>> At the moment my service/rewrite sections are very simple, I pick up
>>>>>> requests with socket.io and send them off to the backend.
>>>>>>
>>>>>> services.xml -
>>>>>>
>>>>>>     <policies>
>>>>>>         <policy role="webappsec"/>
>>>>>>         <policy role="authentication" name="Anonymous"/>
>>>>>>         <policy role="rewrite"/>
>>>>>>         <policy role="authorization"/>
>>>>>>     </policies>
>>>>>>     <routes>
>>>>>>         <route path="/pndaconsole">
>>>>>>         </route>
>>>>>>         <route path="/pndaconsole/**">
>>>>>>           <rewrite apply="PNDACONSOLE/pndaconsole/outbound/app"
>>>>>> to="response.body"/>
>>>>>>         </route>
>>>>>>    </routes>
>>>>>>
>>>>>> rewrite.xml -
>>>>>>
>>>>>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/root"
>>>>>> pattern="*://*:*/**/pndaconsole/">
>>>>>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/"/>
>>>>>>     </rule>
>>>>>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/socket"
>>>>>> pattern="*://*:*/**/pndaconsole/socket.io/?{**}
>>>>>> <http://socket.io/?%7B**%7D>">
>>>>>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/socket.io/?{**}
>>>>>> <http://socket.io/?%7B**%7D>"/>
>>>>>>     </rule>
>>>>>>     <rule dir="IN" name="PNDACONSOLE/pndaconsole/inbound/path"
>>>>>> pattern="*://*:*/**/pndaconsole/{**}">
>>>>>>         <rewrite template="{$serviceUrl[PNDACONSOLE]}/{**}"/>
>>>>>>     </rule>
>>>>>> (I've snipped the rest of the rules handling outbound rewrites as I
>>>>>> don't believe they're relevant, but let me know if you think otherwise)
>>>>>>
>>>>>> By all accounts it looks like it's *nearly* working, but I'm stumped
>>>>>> on where my /socket.io path is going. I was considering routing all
>>>>>> websockets stuff to a completely separate backend/port so that it would 
>>>>>> go
>>>>>> to the right place regardless of how it was rewritten, but that seems a 
>>>>>> bit
>>>>>> extreme and I was hoping to use this approach.
>>>>>>
>>>>>> My end to end is -
>>>>>>
>>>>>> client, an angularjs app  --> knox --> nginx --> reverse proxied
>>>>>> websockets backend in nodejs
>>>>>>
>>>>>> --> flat files, being an angularjs app
>>>>>>
>>>>>> We don't have to use socket.io, I guess, but it is currently used
>>>>>> everywhere so I'd rather avoid swapping that out to get this working if
>>>>>> possible. It's a fairly common library.
>>>>>>
>>>>>> Cheers,
>>>>>>
>>>>>> /ailuropod4 <ailurop...@gmail.com>
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, May 11, 2018 at 8:18 PM, Sandeep Moré <moresand...@gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Hello,
>>>>>>>
>>>>>>> I am not very familiar with socket.io apps, so you might have to
>>>>>>> fill me in about what you are trying to do.
>>>>>>> Looks like you are having issue rewriting Websocket url.
>>>>>>>
>>>>>>> What version of Knox are you using ?
>>>>>>> Knox 0.13.0 and up supports better URL rewriting, see KNOX-776
>>>>>>> <https://issues.apache.org/jira/browse/KNOX-776>, it also has some
>>>>>>> examples in the comments.
>>>>>>>
>>>>>>> What is the ws:// url you are trying to rewrite and the rules you
>>>>>>> are using ?
>>>>>>>
>>>>>>> Best,
>>>>>>> Sandeep
>>>>>>>
>>>>>>> On Fri, May 11, 2018 at 2:54 PM, T Smith <ailurop...@gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> Hi all,
>>>>>>>>
>>>>>>>> I'm struggling to get a simple socket.io based application working
>>>>>>>> through Knox.
>>>>>>>>
>>>>>>>> I see websockets is supported, but the upgrade handshake seems to
>>>>>>>> be nerfed on the way out, specifically the /socket.io/? etc part
>>>>>>>> simply becomes /.
>>>>>>>>
>>>>>>>> I've tried lots of permutations - does anyone have a working
>>>>>>>> example they can point me towards? I've looked at the Zeppelin 
>>>>>>>> approach,
>>>>>>>> but this isn't quite the same thing (not socket.io).
>>>>>>>>
>>>>>>>> Any help appreciated!
>>>>>>>>
>>>>>>>> /ailuropod4 <ailurop...@gmail.com>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

Reply via email to