Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem using https address #2

Open
xukangmin opened this issue Nov 20, 2020 · 6 comments
Open

Problem using https address #2

xukangmin opened this issue Nov 20, 2020 · 6 comments

Comments

@xukangmin
Copy link

xukangmin commented Nov 20, 2020

I'm using https address for ReportingService. I'm hosting a http jsreport server on this address with nginx/certbot (using your suggested config)

The address works perfectly fine with PostMan. I send post request to https://xxx.xxx.xx/api/report/, it gives me 200 with PDF binary.

But when I use client in .NET.

var rs = new ReportingService("https://xxx.xxx.xx/, jsReportUser, jsReportPwd);

inHouseReport = rs.RenderByNameAsync(jsReportTemplateName, quotesData).GetAwaiter().GetResult();

It give me this error:

{StatusCode: 502, ReasonPhrase: 'Bad Gateway', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
  Server: nginx/1.18.0
  Server: (Ubuntu)
  Date: Fri, 20 Nov 2020 21:36:28 GMT
  Connection: keep-alive
  Content-Type: text/html
  Content-Length: 166
}}

I then try to use raw https call using .NET.

                var client = new HttpClient()
                {
                    BaseAddress = new Uri(jsReportURL)
                };


                var json = JsonSerializer.Serialize(rerpotPara);
                var data = new StringContent(json, Encoding.UTF8, "application/json");


                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(
                        Encoding.UTF8.GetBytes(String.Format("{0}:{1}", jsReportUser, jsReportPwd))));

                responseReport = client.PostAsync("api/report", data).GetAwaiter().GetResult();

This is the response:

{StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
  Server: nginx/1.18.0
  Server: (Ubuntu)
  Date: Fri, 20 Nov 2020 21:39:05 GMT
  Transfer-Encoding: chunked
  Connection: keep-alive
  X-Powered-By: Express
  Access-Control-Allow-Origin: *
  Access-Control-Expose-Headers: *
  Set-Cookie: render-complete=true; Path=/
  X-XSS-Protection: 0
  Content-Type: application/pdf
  Content-Disposition: inline; filename=inhousereport-main.pdf
}}

It seems to be httpClient TLS version issue. Check here: https://stackoverflow.com/questions/22251689/make-https-call-using-httpclient

in jsreport-dotnet-client, it's using
Assembly netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51

I'm using
Assembly System.Net.Http, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

Old version of httpClient seems not supporting TLS 1.1+.

My server is using 1.2+ only.

Currently I have to use custom method, hope you can fix it soon. A simple dependency update should solve the problem.

Screenshot 2020-11-20 154225

@pofider
Copy link
Contributor

pofider commented Nov 21, 2020

Are you sure the problem is in the System.Net.Http version?
See the deps in the https://www.nuget.org/packages/jsreport.Client/
image

A .net core app in the VS

image

The 502 error can also mean that the nginx accepted your request, but the proxied node.js server failed to process it.
Please check the jsreport logs, if it receives the request... Doesn't it fail during the processing?

@xukangmin
Copy link
Author

Here is the jsreport log, it actually received the request and process the PDF, somehow the response cannot get back to .NET app. In .net, it still shows error 502.

2020-11-21T22:12:23.973Z - debug: API logging in user kangmin
2020-11-21T22:12:23.973Z - info: Starting rendering request 9 (user: kangmin)
2020-11-21T22:12:23.974Z - info: Rendering template { name: inhousereport-main, recipe: chrome-pdf, engine: handlebars, preview: false }
2020-11-21T22:12:23.974Z - debug: Inline data specified.
2020-11-21T22:12:23.975Z - debug: Resources not defined for this template.
2020-11-21T22:12:23.976Z - debug: Replaced assets ["style.css"]
2020-11-21T22:12:23.976Z - debug: Base url not specified, skipping its injection.
2020-11-21T22:12:23.976Z - debug: Rendering engine handlebars using http-server strategy
2020-11-21T22:12:23.992Z - debug: Taking compiled template from engine cache
2020-11-21T22:12:23.993Z - debug: Executing recipe chrome-pdf
2020-11-21T22:12:24.086Z - debug: Converting with chrome HeadlessChrome/79.0.3945.0 using dedicated-process strategy
2020-11-21T22:12:24.197Z - debug: Page request: GET (document) file:///tmp/jsreport/autocleanup/92181f52-1642-4f1b-98d4-eccb507f041f-chrome-pdf.html
2020-11-21T22:12:24.205Z - debug: Page request finished: GET (document) file:///tmp/jsreport/autocleanup/92181f52-1642-4f1b-98d4-eccb507f041f-chrome-pdf.html
2020-11-21T22:12:24.208Z - debug: Page request: GET (stylesheet) https://cdnjs.cloudflare.com/ajax/libs/metro/4.1.5/css/metro.min.css
2020-11-21T22:12:24.208Z - debug: Page request: GET (script) https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js
2020-11-21T22:12:24.267Z - debug: Page request finished: GET (stylesheet) 200 https://cdnjs.cloudflare.com/ajax/libs/metro/4.1.5/css/metro.min.css
2020-11-21T22:12:24.268Z - debug: Page request finished: GET (script) 200 https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js
2020-11-21T22:12:24.353Z - debug: Running chrome with params {"printBackground":true,"landscape":true,"marginBottom":"1cm","marginRight":"0cm","marginTop":"0cm","marginLeft":"0cm","margin":{"top":"0cm","right":"0cm","bottom":"1cm","left":"0cm"}}
2020-11-21T22:12:24.905Z - info: pdf-utils is starting pdf processing
2020-11-21T22:12:25.074Z - debug: pdf-utils detected 1 pdf operation(s) to process
2020-11-21T22:12:25.074Z - debug: pdf-utils running pdf operation merge
2020-11-21T22:12:25.074Z - info: Starting rendering request 10 (user: kangmin)
2020-11-21T22:12:25.075Z - info: Rendering template { name: header-footer, recipe: chrome-pdf, engine: handlebars, preview: false }
2020-11-21T22:12:25.075Z - debug: Inline data specified.
2020-11-21T22:12:25.076Z - debug: Resources not defined for this template.
2020-11-21T22:12:25.077Z - debug: Replaced assets ["style.css"]
2020-11-21T22:12:25.077Z - debug: Base url not specified, skipping its injection.
2020-11-21T22:12:25.078Z - debug: Rendering engine handlebars using http-server strategy
2020-11-21T22:12:25.089Z - debug: Taking compiled template from engine cache
2020-11-21T22:12:25.090Z - debug: Executing recipe chrome-pdf
2020-11-21T22:12:25.190Z - debug: Converting with chrome HeadlessChrome/79.0.3945.0 using dedicated-process strategy
2020-11-21T22:12:25.285Z - debug: Page request: GET (document) file:///tmp/jsreport/autocleanup/0b010a22-a804-4145-a8b7-d429ab7d803f-chrome-pdf.html
2020-11-21T22:12:25.295Z - debug: Page request finished: GET (document) file:///tmp/jsreport/autocleanup/0b010a22-a804-4145-a8b7-d429ab7d803f-chrome-pdf.html
2020-11-21T22:12:25.297Z - debug: Page request: GET (stylesheet) https://cdnjs.cloudflare.com/ajax/libs/metro/4.1.5/css/metro.min.css
2020-11-21T22:12:25.353Z - debug: Page request finished: GET (stylesheet) 200 https://cdnjs.cloudflare.com/ajax/libs/metro/4.1.5/css/metro.min.css
2020-11-21T22:12:25.365Z - debug: Running chrome with params {"printBackground":true,"marginTop":"0","marginRight":"0","marginLeft":"0","marginBottom":"0.4","landscape":true,"margin":{"top":"0","right":"0","bottom":"0.4","left":"0"}}
2020-11-21T22:12:25.465Z - debug: Skipping storing report.
2020-11-21T22:12:25.466Z - info: Rendering request 10 finished in 392 ms
2020-11-21T22:12:25.709Z - debug: pdf-utils postproces start
2020-11-21T22:12:25.711Z - debug: pdf-utils postproces end
2020-11-21T22:12:25.712Z - info: pdf-utils pdf processing was finished
2020-11-21T22:12:25.712Z - debug: Skipping storing report.
2020-11-21T22:12:25.713Z - info: Rendering request 9 finished in 1740 ms

Here is my NGINX setting.

upstream jsreport {
    # change port 8080 with the port you are running jsreport on
    server 127.0.0.1:5488;
    keepalive 15;
}

limit_req_zone $http_x_forwarded_for zone=login:2m rate=1r/s;



server {
    server_name   reporting.example.com;

    location /socket.io/ {
	    proxy_pass http://jsreport;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
	    proxy_redirect off;
	    proxy_buffers 8 32k;
	    proxy_buffer_size 64k;

	    proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	    proxy_set_header Host $http_host;
    	proxy_set_header X-NginX-Proxy true;
    }

     location /login {
      limit_req zone=login burst=2;
    }

    location / {
        proxy_pass http://127.0.0.1:5488/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }



    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/reporting.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/reporting.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {
    if ($host = reporting.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    server_name   reporting.example.com;
    listen 80;
    return 404; # managed by Certbot


}

@xukangmin
Copy link
Author

I confirm it's not dependency issue, more like a request issue.

I make a test function in the library. It works fine.

        public HttpResponseMessage RenderByName(string url, string user, string pwd, string testData)
        {
            var client = new HttpClient()
            {
                BaseAddress = new Uri(url)
            };

            testRequest = testData;

            var data = new StringContent(testData, Encoding.UTF8, "application/json");

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(
                    Encoding.UTF8.GetBytes(String.Format("{0}:{1}", user, pwd))));

            var responseReport = client.PostAsync("api/report", data).GetAwaiter().GetResult();

            return responseReport;
        }

I then test using the same request string, then RenderByNameAsync works fine.

Seems it's me passing the wrong data object, I will keep you updated.

@xukangmin
Copy link
Author

xukangmin commented Nov 21, 2020

There is a "options" key in the request which results in 502 Bad Gateway, if I remove "Options", it works fine. I tested in both PostMan and .Net. Any ideas?

(If I set "logsToResponseHeader" to false, it works)

"options" is added by RenderByNameAsync.

Working Request: (status 200)

{
    "template": {
        "name": "inhousereport-main"
    },
    "data": {
        "activeinhouse": 61472.30078125,
        "totalinhouse": 67134.296875,
        "currentdate": "11/21/2020",
        "openquote30": 0.0,
        "openquote90": 0.0,
        "saleslastday": 0.0,
        "saleslastdaydate": "2020-11-20T00:00:00",
        "salesthismonth": 0.0,
        "quotes": [
            {
                "ncus": 0,
                "exp": "2",
                "caltype": "AF",
                "po": "54535",
                "quoteid": "QTE002046",
                "mfg": "VPFlowscope",
                "customer": "Martin Calibration",
                "cert": "76960-23245",
                "calprice": 913.5,
                "datein": "2019-07-29",
                "datedue": "2019-07-31",
                "due": 193,
                "status": "Calibration Complete Awaiting Tech Review",
                "sortNumber": 66960
            },
            {
                "ncus": 1,
                "exp": "5",
                "caltype": "Vel",
                "po": "237454 OP",
                "quoteid": "19197",
                "mfg": "Amprobe",
                "customer": "Fike Corporation",
                "cert": "70780",
                "calprice": 264,
                "datein": "2018-09-26",
                "datedue": "2018-10-03",
                "due": 408,
                "status": "Trashed",
                "sortNumber": 70780
            }
        ]
    }
}

Not Working Request: (Status 502)

{
  "$id": "1",
  "template": {
    "$id": "2",
    "name": "inhousereport-main"
  },
  "options": {
    "$id": "3",
    "debug": {
      "$id": "4",
      "logsToResponseHeader": true
    }
  },
  "data": {
    "$id": "5",
    "activeinhouse": 61472.30078125,
    "totalinhouse": 67134.296875,
    "currentdate": "11/21/2020",
    "openquote30": 0.0,
    "openquote90": 0.0,
    "saleslastday": 0.0,
    "saleslastdaydate": "2020-11-20T00:00:00",
    "salesthismonth": 0.0,
    "quotes": [
      {
        "$id": "6",
        "ncus": 0,
        "exp": 5,
        "caltype": "AF",
        "po": "7202110809",
        "quoteid": "QTE002667",
        "mfg": "Matheson",
        "customer": "UL LLC",
        "certid": "78003-78004",
        "calprice": 229.0,
        "datein": "2019-09-16",
        "datedue": "2019-09-23",
        "due": 304,
        "status": "Calibration Complete Awaiting Tech Review",
        "sortnumber": 78004
      },
      {
        "$id": "7",
        "ncus": 0,
        "exp": 5,
        "caltype": "AF",
        "po": "58760",
        "quoteid": "QTE005170",
        "mfg": "Dwyer",
        "customer": "Martin Calibration",
        "certid": "82377",
        "calprice": 504.0,
        "datein": "2020-04-23",
        "datedue": "2020-04-30",
        "due": 146,
        "status": "Calibration In Progress",
        "sortnumber": 82377
      }
    ]
  }
}

@xukangmin
Copy link
Author

2 solutions now.

  1. Disable logsToResponseHeader, by using RenderAsync with customized request.
                rs.RenderAsync(new RenderRequest()
                {
                    Template = new Template()
                    {
                        Name = "sales-order"
                    },
                    Data = data,
                    Options = new RenderOptions() { Debug = new DebugOptions() { LogsToResponseHeader = false } }
                })
  1. Increase Nginx buffer size
    location / {
        proxy_pass http://127.0.0.1:5488/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        proxy_buffer_size          128k;
        proxy_buffers              4 256k;
        proxy_busy_buffers_size    256k;

    }

At this point it's not a bug per say, I'm suggesting changing RenderByNameAsync debug option logsToResponseHeader to false by default or change your documentation about Nginx configuration.

@pofider
Copy link
Contributor

pofider commented Nov 22, 2020

Yes, we will completely remove the logsToResponseHeader in the next version in the next major release.
I didn't expect it will cause such bad errors. My apologies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants