http2请求返回错误请求

时间:2019-07-01 20:29:50

标签: c sockets curl request http2

我有一个套接字C语言程序,必须使用http2协议。它返回错误请求-HTTP错误400。请求的格式错误。

最初,我通过curl 7.64发送了如下请求:

curl -v -http2 -i https://mywebsite.xyz 

我得到以下输出:

* Expire in 0 ms for 6 (transfer 0x55cc25ec95c0)
* Expire in 1 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 0 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 1 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 0 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 0 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 1 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 0 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 0 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 2 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 1 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 1 ms for 1 (transfer 0x55cc25ec95c0)
* Expire in 2 ms for 1 (transfer 0x55cc25ec95c0)
*   Trying 10.8.0.253...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55cc25ec95c0)
* Connected to mysite.xyz (10.8.0.253) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=US; postalCode=XXXX; ST=XX; L=XXXXX; street=XXXXXXXXXXXX; O=XXXXXX; OU=PremiumSSL Wildcard; CN=*.XXXXXXX
*  start date: Nov 20 00:00:00 2018 GMT
*  expire date: Feb 21 23:59:59 2021 GMT
*  subjectAltName: host "mysite.xyz" matched cert's "*.mysite.xyz"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Organization Validation Secure Server CA
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x55cc25ec95c0)
> GET / HTTP/2
> Host: mysite.xyz
> User-Agent: curl/7.64.0
> Accept: */*
> 
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200 
HTTP/2 200 
< content-type: text/html
content-type: text/html
< last-modified: Mon, 01 Jul 2019 17:57:17 GMT
last-modified: Mon, 01 Jul 2019 17:57:17 GMT
< accept-ranges: bytes
accept-ranges: bytes
< etag: "c7c5406c3630d51:0"
etag: "c7c5406c3630d51:0"
< server: Microsoft-IIS/10.0
server: Microsoft-IIS/10.0
< date: Mon, 01 Jul 2019 19:45:53 GMT
date: Mon, 01 Jul 2019 19:45:53 GMT
< content-length: 51
content-length: 51

< 
<html>
<head></head>
</body>Hello</body>
* Connection #0 to host mysite.xyz left intact
</html>

从上面的请求-响应日志中,我得到了以下内容:

GET / HTTP/2
Host: mysite.xyz
User-Agent: curl/7.64.0
Accept: */*

并创建了如下请求:

char* inputString = "GET / HTTP/2\r\nHost: mysite.xyz\r\nUser-Agent: curl/7.64.0\r\nAccept: */*\r\n\r\n"

但是,这次我遇到了类似的错误:

Connected with ECDHE-RSA-AES256-GCM-SHA384 encryption
Received: "HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 01 Jul 2019 20:28:48 GMT
Connection: close
Content-Length: 311

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request</h2>
<hr><p>HTTP Error 400. The request is badly formed.</p>
</BODY></HTML>

1 个答案:

答案 0 :(得分:2)

HTTP / 2不是像HTTP / 1这样的基于“简单”文本的协议。这意味着您不能只将HTTP请求作为文本发送到TCP套接字,而必须使用(相当复杂的)HTTP / 2标准定义的请求的二进制表示形式。 curl在调试输出中显示的只是请求的文本解释,而不是线路上的实际表示。有关更多信息,请参见RFC 7540。请注意,除了二进制封装,您还需要将TLS中的ALPN扩展名设置为h2,以便向服务器宣布您将使用HTTP / 2。

在您的特定情况下,请求以基于文本的方式发送(未设置ALPN h2,并且没有HTTP / 2封装),但是基于文本的协议规范未知,即HTTP/2而不是HTTP/1.1或类似名称。因此,服务器将请求正确视为无效。