mkopylec / charon-spring-boot-starter

Reverse proxy implementation in form of a Spring Boot starter.
Apache License 2.0
245 stars 55 forks source link

Is there XHR support available? #42

Closed dmarko484 closed 6 years ago

dmarko484 commented 6 years ago

When working with Grafana behind Charon reverse proxy I found out, that some(many) Grafana parts/pages are not working. After investigation I found out, that XHR(ajax) calls are not proxied properly. Grafana is using Angular that communicates with server using ajax/xhr . These requests remain as pending in browser ... that means that request was send to charon, but there is no reply back. (see screenshot from browser)

image

In SpringBoot I can see this request beeing forwarded (see below) but somehow no response is sent back to browser: c.g.m.charon.core.http.RequestForwarder : Forwarding: GET /grafana/api/dashboards/db/es-polna -> http://localhost:3000/api/dashboards/db/es-polna 200

Any idea what is wrong here?

mkopylec commented 6 years ago

The log you pasted clearly states that the response was received by Charon with HTTP 200 status. From the browser screenshot I see that the browser also reveived HTTP 200 response. Hard to say what's wrong. Please try another browsers and also try to enable "tracing" and check the logs, they should contain detailed information about requests and responses, see here: https://github.com/mkopylec/charon-spring-boot-starter#tracing. Also check headers and body in browser.

dmarko484 commented 6 years ago

It really returns proper response headers, but chrome says that is still wating for data (the same with other browsers)

image

Explanation link points to https://developers.google.com/web/tools/chrome-devtools/network-performance/reference#timing-explanation

dmarko484 commented 6 years ago

Tracing enabled, I can see proper data in onForwardComplete ... but nothing get back to browser actualy. (only failed requests are these that Grafana handles as XHR/Ajax). Otherwise I can't see any other errors. Such requests are simply running forever in browser as they wait for data from server.

Only I can see is that Grafana response is JSON ...

But headers in browser are correct I think:

image

@Override
    public void onForwardComplete(String traceId, ReceivedResponse response) {
        print("onForwardComplete: "+response.getBodyAsString());
    }

... shows this:

onForwardComplete: {"meta":{"type":"db","canSave":true,"canEdit":true,"canStar":true,"slug":"es-polna","expires":"0001-01-01T00:00:00Z","created":"2018-02-02T12:58:55+01:00","updated":"2018-02-02T12:58:55+01:00","updatedBy":"admin","createdBy":"admin","version":1},"dashboard":{"annotations":{"list":[{"builtIn":1,"datasource":"-- Grafana --","enable":true,"hide":true,"iconColor":"rgba(0, 211, 255, 1)","name":"Annotations \u0026 Alerts","type":"dashboard"}]},"editable":true,"gnetId":null,"graphTooltip":0,"hideControls":false,"id":1,"links":[],"rows":[{"collapse":false,"height":"250px","panels":[{"aliasColors":{},"bars":false,"dashLength":10,"dashes":false,"datasource":"ES netnotes","fill":1,"id":1,"legend":{"avg":false,"current":false,"max":false,"min":false,"show":true,"total":false,"values":false},"lines":true,"linewidth":1,"links":[],"nullPointMode":"null","percentage":false,"pointradius":5,"points":false,"renderer":"flot","seriesOverrides":[],"spaceLength":10,"span":12,"stack":false,"steppedLine":false,"targets":[{"bucketAggs":[{"field":"updatedDate","id":"2","settings":{"interval":"auto","min_doc_count":0,"trimEdges":0},"type":"date_histogram"}],"dsType":"elasticsearch","metrics":[{"field":"select field","id":"1","type":"count"}],"refId":"A","timeField":"updatedDate"}],"thresholds":[],"timeFrom":null,"timeShift":null,"title":"Panel Title","tooltip":{"shared":true,"sort":0,"value_type":"individual"},"type":"graph","xaxis":{"buckets":null,"mode":"time","name":null,"show":true,"values":[]},"yaxes":[{"format":"short","label":null,"logBase":1,"max":null,"min":null,"show":true},{"format":"short","label":null,"logBase":1,"max":null,"min":null,"show":true}]}],"repeat":null,"repeatIteration":null,"repeatRowId":null,"showTitle":false,"title":"Dashboard Row","titleSize":"h6"}],"schemaVersion":14,"style":"dark","tags":[],"templating":{"list":[]},"time":{"from":"now-6h","to":"now"},"timepicker":{"refresh_intervals":["5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"],"time_options":["5m","15m","1h","6h","12h","24h","2d","7d","30d"]},"timezone":"","title":"ES Polna","version":1}}

mkopylec commented 6 years ago

Interesting case. Here is some information about the TTFB problem: https://scaleyourcode.com/blog/article/27 Screen with request headers could be useful.

dmarko484 commented 6 years ago

Tried different browsers, the same results. If I go to URL directly without Charon, it runs correctly. My only observation is that problematic are XHX/Ajax requests.

Here are complete headers ... - it sends complete response header but not content/body. image

RichardBradley commented 6 years ago

My guess would be that there is some kind of transport-level mismatch. I fixed some bugs that might have caused this in commit 2e4768465c44

Please could you:

  1. Retest on the current version, which includes the above fixes
  2. If not fixed, post here the output from from curl -v to both the Charon endpoint and the upstream endpoint?
  3. If at all possible, post a repro case that we can try?
dmarko484 commented 6 years ago

Do you suppose to release a new version here with these fixes?

RichardBradley commented 6 years ago

Version 2.4.0 includes the fix and is available on Maven central

dmarko484 commented 6 years ago

Upgraded to Charon 2.5.0 and ... GREAT! Its working!!! Tried with latest Grafana https://grafana.com/ (v. 5.1.3) configured for reverse proxy auth. I'm succesfully forwarding username from SpringBoot app to Grafana using http headers (using ForwardedRequestInterceptor) and all XHR requests are working fine now. Great solution.

mkopylec commented 6 years ago

Great to hear 🙂 Im closing the issue then