qicosmos / cinatra

modern c++(c++20), cross-platform, header-only, easy to use http framework
MIT License
1.81k stars 369 forks source link

https question #572

Open manuel76413 opened 2 months ago

manuel76413 commented 2 months ago

URL example:
https://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2

when visiting by Chrome, it's ok, the response data is a tiled image.

I tested using Cinatra, however, the response value is 400.

so can someone teach me how to solve the problem :-)

qicosmos commented 2 months ago

you need add definition: CINATRA_ENABLE_SSL, set it as ON. and make sure you have installed openssl.

manuel76413 commented 2 months ago

Yes, I defined the CINATRA_ENABLE_SSL macro and linked it to libssl 1.0.2. I was able to compile and link successfully. However, when I tried to set a proxy, the v2ray software crashed. So instead, I tried setting up a https uri that doesn't require a proxy, but it didn't work correctly. the response value is 400.

manuel76413 commented 2 months ago

test code :

include "cinatra.hpp"

void testhttpstile_cinatra() {

ifdef CINATRA_ENABLE_SSL

cinatra::coro_http_client client2{}; client2.init_ssl(); auto result = client2.get("https://baidu.com"); assert(result.status == 200);

client2.set_proxy("127.0.0.1", "10809"); auto result1 = client2.get("https://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2"); assert(result1.status == 200);

endif

}

call client2.get("https://baidu.com") result.resp_body is :

<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>bfe/1.0.8.18</center>
</body>
</html>

call client2.get("https://mt.google.com/.... result.resp_body is:

<html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>bfe/1.0.8.18</center>
</body
qicosmos commented 2 months ago

use a new client to call google, one host one client.

qicosmos commented 2 months ago

no need to call init_ssl

manuel76413 commented 2 months ago

after use seperate client, and comment init_ssl call, the result status is 302 and 404. I add CINATRA_ENABLE_SSL, but while compiling, cinatra didn't ask to include ssl head and link to ssl library? maybe my path has contain ssl sdk?

manuel76413 commented 2 months ago

I catch message from v2rayN,the client.get function call cause message like

2024/04/30 09:50:17 [Warning] [2497071007] app/proxyman/inbound: connection ends > proxy/http: failed to read http request > malformed HTTP request "\x16\x03\x01\x016\x01\x00\x012\x03\x03\xbc$\x87\x1c\x0e\xc6\vl^c\x9d\x81Ƞ\xed\x92h\x918u\x86\x98hAw\x1c\xbeq\xa8\xbb\xd0\x02 \f\xbc[\xb8\xc2!u\xccӊ;\xe0\xd1\r-9(j\x88\xd1\t#(\xb3\x0eڪ\xc5\xed\xff\xc0W\x00>\x13\x02\x13\x03\x13\x01\xc0,\xc00\x00\x9f̨̩̪\xc0+\xc0/\x00\x9e\xc0$\xc0(\x00k\xc0#\xc0'\x00g\xc0"

the correct should like accepted //mt.google.com:443

I don't know why, how to solve

qicosmos commented 2 months ago

if you call "https://baidu.com/" get 302, it's ok. I think call google is similar.

qicosmos commented 2 months ago

I catch message from v2rayN,the client.get function call cause message like

2024/04/30 09:50:17 [Warning] [2497071007] app/proxyman/inbound: connection ends > proxy/http: failed to read http request > malformed HTTP request "\x16\x03\x01\x016\x01\x00\x012\x03\x03\xbc$\x87\x1c\x0e\xc6\vl^c\x9d\x81Ƞ\xed\x92h\x918u\x86\x98hAw\x1c\xbeq\xa8\xbb\xd0\x02 \f\xbc[\xb8\xc2!u\xccӊ;\xe0\xd1\r-9(j\x88\xd1\t#(\xb3\x0eڪ\xc5\xed\xff\xc0W\x00>\x13\x02\x13\x03\x13\x01\xc0,\xc00\x00\x9f̨̩̪\xc0+\xc0/\x00\x9e\xc0$\xc0(\x00k\xc0#\xc0'\x00g\xc0"

the correct should like accepted //mt.google.com:443

I don't know why, how to solve

if you don't use proxy, visit goole directly i think it's ok, you can have a try.

helintongh commented 2 months ago

Use http, maybe your proxy software does not support https.

My vpn doesn't support it.

Like this:

image

According to your v2ray message, it only supports http proxy.Change to use http and it will be successful.

  coro_http_client client3{};
  client3.set_proxy("192.168.102.1", "7890");
  auto result1 = client3.get("http://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2");
  std::cout << result1.status << std::endl;

status is 200.

manuel76413 commented 2 months ago

Hi helintongh, thanks for your reply.

you get the correct status 200, so ... I don't know which part is faulty, maybe the program linked to the wrong SSL library or something else.

but I test another library called httplib, get the same URI, it's OK, I got 200 and can save the tile image. so I think cinatra is good, the proxy is good, it must something I didn't put correctly.

the httplib test code is follow:

#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "httplib.h"
void testhttpstile_httplib(std::string uri = "https://mt.google.com")
{
  httplib::Client cli(uri);
  cli.set_proxy("127.0.0.1", 10809);
  auto res = cli.Get("/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2");
  res->status;
  res->body;
}
manuel76413 commented 2 months ago

and I reported a typo, in coro_http_client.hpp, init_config function, if (!conf.proxy_host.empty()) { I think should call set_proxy, but the current code calls set_proxy_basic_auth.

Is this a typo?

manuel76413 commented 2 months ago

Use http, maybe your proxy software does not support https.

My vpn doesn't support it.

Like this:

image

According to your v2ray message, it only supports http proxy.Change to use http and it will be successful.

  coro_http_client client3{};
  client3.set_proxy("192.168.102.1", "7890");
  auto result1 = client3.get("http://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2");
  std::cout << result1.status << std::endl;

status is 200.

No, I need to solve https, for many uri don't have http version.

helintongh commented 2 months ago

Use http, maybe your proxy software does not support https. My vpn doesn't support it. Like this: image According to your v2ray message, it only supports http proxy.Change to use http and it will be successful.

  coro_http_client client3{};
  client3.set_proxy("192.168.102.1", "7890");
  auto result1 = client3.get("http://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2");
  std::cout << result1.status << std::endl;

status is 200.

No, I need to solve https, for many uri don't have http version.

It is currently confirmed that cinatra does not support https proxy for the time being.I will complete this feature tomorrow.The https proxy must first establish a connection with the server through http and then forward it.

helintongh commented 2 months ago

and I reported a typo, in coro_http_client.hpp, init_config function, if (!conf.proxy_host.empty()) { I think should call set_proxy, but the current code calls set_proxy_basic_auth.

Is this a typo?

@qicosmos Is it?

qicosmos commented 2 months ago

set_proxy is better.

helintongh commented 3 weeks ago

in pr solve this question.

example code is as following:

#include <iostream>

#include "../include/cinatra.hpp"
#include "cinatra/ylt/metric/gauge.hpp"
#include "cinatra/ylt/metric/histogram.hpp"
#include "cinatra/ylt/metric/summary.hpp"

using namespace cinatra;
using namespace std::chrono_literals;

int main() {
  // use_metric();
  coro_http_client client{};
  client.set_proxy("192.168.16.1", "7890");
    // auto ret = client.async_request(url, http_method::GET, req_context<>{}, {},
    //                                 std::span<char>{str.data(), str.size()});
    // auto result = async_simple::coro::syncAwait(ret);
  std::unordered_map<std::string, std::string> headers = {
    {"User-Agent", "cpp-httplib/0.15.3"},
    {"Connection", "close"}
  };
  std::string uri = "https://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2";
  auto result1 = async_simple::coro::syncAwait(client.async_request_upgrade(uri, http_method::GET, req_context<>{}, headers));
  std::cout << result1.status << std::endl;
  return 0;
}
manuel76413 commented 5 days ago

in pr solve this question.

example code is as following:

#include <iostream>

#include "../include/cinatra.hpp"
#include "cinatra/ylt/metric/gauge.hpp"
#include "cinatra/ylt/metric/histogram.hpp"
#include "cinatra/ylt/metric/summary.hpp"

using namespace cinatra;
using namespace std::chrono_literals;

int main() {
  // use_metric();
  coro_http_client client{};
  client.set_proxy("192.168.16.1", "7890");
    // auto ret = client.async_request(url, http_method::GET, req_context<>{}, {},
    //                                 std::span<char>{str.data(), str.size()});
    // auto result = async_simple::coro::syncAwait(ret);
  std::unordered_map<std::string, std::string> headers = {
    {"User-Agent", "cpp-httplib/0.15.3"},
    {"Connection", "close"}
  };
  std::string uri = "https://mt.google.com/vt/lyrs=t,r&hl=x-local&src=app&apistyle=s.t%3A0%7Cs.e%3Al%7Cp.v%3Aoff&x=1&y=3&z=2";
  auto result1 = async_simple::coro::syncAwait(client.async_request_upgrade(uri, http_method::GET, req_context<>{}, headers));
  std::cout << result1.status << std::endl;
  return 0;
}

I pulled the last code but still did not support HTTPS, there is no async_request_upgrade method in the coro_http_client class.