TIL (Today I Learned)/Network

[Network] HTTP/2 지원여뢀 νŒλ‹¨ C둜 κ΅¬ν˜„

loki d 2021. 9. 13. 16:39
728x90

HTTP/2 check ν•΄μ£ΌλŠ” C둜 κ΅¬ν˜„

HTTP Request Header

image

HTTP Status Code

image

1xx

  • 100 Continue
    μ§„ν–‰ μ€‘μž„μ„ μ˜λ―Έν•˜λŠ” μ‘λ‹΅μ½”λ“œμž…λ‹ˆλ‹€. ν˜„μž¬κΉŒμ§€μ˜ μ§„ν–‰μƒνƒœμ— λ¬Έμ œκ°€ μ—†μœΌλ©°, ν΄λΌμ΄μ–ΈνŠΈκ°€ κ³„μ†ν•΄μ„œ μš”μ²­μ„ ν•˜κ±°λ‚˜ 이미 μš”μ²­μ„ μ™„λ£Œν•œ κ²½μš°μ—λŠ” λ¬΄μ‹œν•΄λ„ λ˜λŠ” 것을 μ•Œλ €μ€λ‹ˆλ‹€.
  • 101 Switching Protocol
    101은 ν΄λΌμ΄μ–ΈνŠΈμ— μ˜ν•΄ 보낸 μ—…κ·Έλ ˆμ΄λ“œ μš”μ²­ 헀더에 λŒ€ν•œ μ‘λ‹΅μœΌλ‘œ λ³΄λ‚΄μ§‘λ‹ˆλ‹€. 이 응닡 μ½”λ“œλŠ” ν΄λΌμ΄μ–ΈνŠΈκ°€ 보낸 Upgrade μš”μ²­ 헀더에 λŒ€ν•œ 응닡에 λ“€μ–΄κ°€λ©°, μ„œλ²„μ—μ„œ ν”„λ‘œν† μ½œμ„ λ³€κ²½ν•  κ²ƒμž„μ„ μ•Œλ €μ€λ‹ˆλ‹€. ν•΄λ‹Ή μ½”λ“œλŠ” Websocket ν”„λ‘œν† μ½œ μ „ν™˜ μ‹œμ— μ‚¬μš©λ©λ‹ˆλ‹€.
  • 102 Processing(WebDAV)
    이 응닡 μ½”λ“œλŠ” μ„œλ²„κ°€ μš”μ²­μ„ μˆ˜μ‹ ν•˜μ˜€μœΌλ©° 이λ₯Ό μ²˜λ¦¬ν•˜κ³  μžˆμ§€λ§Œ, 아직 μ œλŒ€λ‘œ 된 응닡을 μ•Œλ €μ€„ 수 μ—†μŒμ„ μ•Œλ €μ€λ‹ˆλ‹€.

2xx

  • 200 OK
    μš”μ²­μ΄ μ„±κ³΅μ μœΌλ‘œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ •λ³΄λŠ” μš”μ²­μ— λ”°λ₯Έ μ‘λ‹΅μœΌλ‘œ λ°˜ν™˜λ©λ‹ˆλ‹€.
  • 201 Created
    μš”μ²­μ΄ μ„±κ³΅μ μ΄μ—ˆμœΌλ©° κ·Έ 결과둜 μƒˆλ‘œμš΄ λ¦¬μ†ŒμŠ€κ°€ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이 응닡은 일반적으둜 POST μš”μ²­ λ˜λŠ” 일뢀 PUT μš”μ²­ 이후에 λ”°λΌμ˜΅λ‹ˆλ‹€.
  • 202 Accepted
    μš”μ²­μ„ μˆ˜μ‹ ν•˜μ˜€μ§€λ§Œ, 그에 μ‘ν•˜μ—¬ 행동할 수 μ—†μŠ΅λ‹ˆλ‹€. 이 응닡은 μš”μ²­ μ²˜λ¦¬μ— λŒ€ν•œ κ²°κ³Όλ₯Ό 이후에 HTTP둜 비동기 응닡을 λ³΄λ‚΄λŠ” 것에 λŒ€ν•΄μ„œ λͺ…ν™•ν•˜κ²Œ λͺ…μ‹œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이것은 λ‹€λ₯Έ ν”„λ‘œμ„ΈμŠ€μ—μ„œ 처리 λ˜λŠ” μ„œλ²„κ°€ μš”μ²­μ„ 닀루고 μžˆκ±°λ‚˜ 배치 ν”„λ‘œμ„ΈμŠ€λ₯Ό ν•˜κ³  μžˆλŠ” 경우λ₯Ό μœ„ν•΄ λ§Œλ“€μ–΄μ‘ŒμŠ΅λ‹ˆλ‹€.

3xx

  • 300 Multiple Choices
    μ΅œλŒ€ λ‹€μ„― 개의 링크λ₯Ό κ³¨λΌμ„œ 이동할 수 μžˆλŠ” μƒνƒœ
  • 301 Moved Permanently
    이 응닡 μ½”λ“œλŠ” μš”μ²­ν•œ λ¦¬μ†ŒμŠ€μ˜ URIκ°€ λ³€κ²½λ˜μ—ˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. μƒˆλ‘œμš΄ URIκ°€ μ‘λ‹΅μ—μ„œ μ•„λ§ˆλ„ μ£Όμ–΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 302 Found
    이 응닡 μ½”λ“œλŠ” μš”μ²­ν•œ λ¦¬μ†ŒμŠ€μ˜ URIκ°€ μΌμ‹œμ μœΌλ‘œ λ³€κ²½λ˜μ—ˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. μƒˆλ‘­κ²Œ λ³€κ²½λœ URIλŠ” λ‚˜μ€‘μ— λ§Œλ“€μ–΄μ§ˆ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ, ν΄λΌμ΄μ–ΈνŠΈλŠ” ν–₯ν›„μ˜ μš”μ²­λ„ λ°˜λ“œμ‹œ λ™μΌν•œ URI둜 ν•΄μ•Όν•©λ‹ˆλ‹€.
  • 303 See Other
    ν΄λΌμ΄μ–ΈνŠΈκ°€ μš”μ²­ν•œ λ¦¬μ†ŒμŠ€λ₯Ό λ‹€λ₯Έ URIμ—μ„œ GET μš”μ²­μ„ 톡해 μ–»μ–΄μ•Ό ν•  λ•Œ, μ„œλ²„κ°€ ν΄λΌμ΄μ–ΈνŠΈλ‘œ 직접 λ³΄λ‚΄λŠ” μ‘λ‹΅μž…λ‹ˆλ‹€.
  • 304 Not Modified
    이것은 μΊμ‹œλ₯Ό λͺ©μ μœΌλ‘œ μ‚¬μš©λ©λ‹ˆλ‹€. 이것은 ν΄λΌμ΄μ–ΈνŠΈμ—κ²Œ 응닡이 μˆ˜μ •λ˜μ§€ μ•Šμ•˜μŒμ„ μ•Œλ €μ£Όλ©°, κ·ΈλŸ¬λ―€λ‘œ ν΄λΌμ΄μ–ΈνŠΈλŠ” κ³„μ†ν•΄μ„œ μ‘λ‹΅μ˜ μΊμ‹œλœ 버전을 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • 305 Use Proxy
    이전 λ²„μ „μ˜ HTTP 기술 μ‚¬μ–‘μ—μ„œ μ •μ˜λ˜μ—ˆμœΌλ©°, μš”μ²­ν•œ 응닡은 λ°˜λ“œμ‹œ ν”„λ‘μ‹œλ₯Ό ν†΅ν•΄μ„œ 접속해야 ν•˜λŠ” 것을 μ•Œλ €μ€λ‹ˆλ‹€. 이것은 ν”„λ‘μ‹œμ˜ in-band섀정에 λŒ€ν•œ λ³΄μ•ˆμƒμ˜ κ±±μ •μœΌλ‘œ μΈν•˜μ—¬ 사라져가고 μžˆμŠ΅λ‹ˆλ‹€.

4xx

  • 400 Bad Request
    응닡은 잘λͺ»λœ λ¬Έλ²•μœΌλ‘œ μΈν•˜μ—¬ μ„œλ²„κ°€ μš”μ²­ν•˜μ—¬ 이해할 수 μ—†μŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.
  • 401 Unauthorized
    비둝 HTTP ν‘œμ€€μ—μ„œλŠ” '미승인(unauthorized)'λ₯Ό λͺ…ν™•νžˆ ν•˜κ³  μžˆμ§€λ§Œ, μ˜λ―Έμƒ 이 응닡은 '비인증(unauthenticated)'λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈλŠ” μš”μ²­ν•œ 응닡을 λ°›κΈ° μœ„ν•΄μ„œλŠ” λ°˜λ“œμ‹œ 슀슀둜λ₯Ό 인증해야 ν•©λ‹ˆλ‹€.
  • 402
    이 응닡 μ½”λ“œλŠ” λ‚˜μ€‘μ— μ‚¬μš©λ  것을 λŒ€λΉ„ν•΄ μ˜ˆμ•½λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 첫 λͺ©ν‘œλ‘œλŠ” λ””μ§€ν„Έ 결제 μ‹œμŠ€ν…œμ— μ‚¬μš©ν•˜κΈ° μœ„ν•˜μ—¬ λ§Œλ“€μ–΄μ‘Œμ§€λ§Œ μ§€κΈˆ μ‚¬μš©λ˜κ³  μžˆμ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€.
  • 403 Forbidden
    ν΄λΌμ΄μ–ΈνŠΈλŠ” μ½˜ν…μΈ μ— μ ‘κ·Όν•  ꢌ리λ₯Ό κ°€μ§€κ³  μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 그듀은 λ―ΈμŠΉμΈμ΄μ–΄μ„œ μ„œλ²„λŠ” κ±°μ ˆμ„ μœ„ν•œ μ μ ˆν•œ 응닡을 λ³΄λƒ…λ‹ˆλ‹€. 401κ³Ό λ‹€λ₯Έ 점은 μ„œλ²„κ°€ ν΄λΌμ΄μ–ΈνŠΈκ°€ λˆ„κ΅¬μΈμ§€ μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€.
  • 404 Not Found
    μ„œλ²„λŠ” μš”μ²­λ°›μ€ λ¦¬μ†ŒμŠ€λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€. λΈŒλΌμš°μ €μ—μ„œλŠ” μ•Œλ €μ§€μ§€ μ•Šμ€ URL을 μ˜λ―Έν•©λ‹ˆλ‹€. 이것은 APIμ—μ„œ 쒅점은 μ μ ˆν•˜μ§€λ§Œ λ¦¬μ†ŒμŠ€ μžμ²΄λŠ” μ‘΄μž¬ν•˜μ§€ μ•ŠμŒμ„ μ˜λ―Έν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ„œλ²„λ“€μ€ 인증받지 μ•Šμ€ ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„° λ¦¬μ†ŒμŠ€λ₯Ό 숨기기 μœ„ν•˜μ—¬ 이 응닡을 403 λŒ€μ‹ μ— 전솑할 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 이 응닡 μ½”λ“œλŠ” μ›Ήμ—μ„œ 반볡적으둜 λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— κ°€μž₯ 유λͺ…할지도 λͺ¨λ¦…λ‹ˆλ‹€.

5xx

  • 500 Internal Server Error
    μ›Ή μ‚¬μ΄νŠΈ μ„œλ²„μ— λ¬Έμ œκ°€ μžˆμŒμ„ μ˜λ―Έν•˜μ§€λ§Œ μ„œλ²„λŠ” μ •ν™•ν•œ λ¬Έμ œμ— λŒ€ν•΄ 더 ꡬ체적으둜 μ„€λͺ…ν•  수 μ—†μŠ΅λ‹ˆλ‹€.
  • 501 Not Implemented
    μ„œλ²„κ°€ μš”μ²­μ„ μ΄ν–‰ν•˜λŠ” 데 ν•„μš”ν•œ κΈ°λŠ₯을 μ§€μ›ν•˜μ§€ μ•ŠμŒμ„ λ‚˜νƒ€λƒ…λ‹ˆλ‹€.
  • 502 Bad Gateway
    μ„œλ²„κ°€ κ²Œμ΄νŠΈμ›¨μ΄λ‘œλΆ€ν„° 잘λͺ»λœ 응닡을 μˆ˜μ‹ ν–ˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. μΈν„°λ„·μƒμ˜ μ„œλ²„κ°€ λ‹€λ₯Έ μ„œλ²„λ‘œλΆ€ν„° μœ νš¨ν•˜μ§€ μ•Šμ€ 응닡을 받은 경우 λ°œμƒν•©λ‹ˆλ‹€.

    처음 μ‹œλ„

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>

char buffer[BUFSIZ];

int main(int argc, char *argv[]){
        int status;
        struct addrinfo hints;
        struct addrinfo *servinfo, *tmp;                // κ²°κ³Όλ₯Ό μ €μž₯ν•  λ³€μˆ˜
        char host[256];
        int c_socket;
        struct sockaddr_in c_addr;
        int len;

        char rcvBuffer[BUFSIZ];
        int n;

        c_socket = socket(PF_INET, SOCK_STREAM, 0);


        memset(&hints, 0, sizeof(hints));               // hints ꡬ쑰체의 λͺ¨λ“  값을 0으둜 μ΄ˆκΈ°ν™”
        hints.ai_family = AF_UNSPEC;                    // IPv4 IPv6 상관없이 κ²°κ³Ό λͺ¨λ‘ λ°˜ν™˜
        hints.ai_socktype = SOCK_STREAM;                // TCP stream sockets

        if(argc ==1){
                printf("Enter Domain\n ");
                return -1;
        }
        status = getaddrinfo(argv[1], "80", &hints, &servinfo);

        tmp = servinfo;
        getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);

        sprintf(buffer, "GET / HTTP/1.1\r\nHost: %s\r\nConnection: %s\r\nUpgrade: %s\r\nHTTP2-Settings: %s\r\n\r\n", argv[1], "Upgrade, HTTP2-Settings", "h2c", "<base64url encoding of HTTP/2 SETTINGS payload>");

        memset(&c_addr, 0, sizeof(c_addr));
        c_addr.sin_addr.s_addr = inet_addr(host);
        c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(80);

        printf("hostname : %s\n", host);

        if(connect(c_socket, (struct sockaddr *) &c_addr, sizeof(c_addr)) == -1){
                printf("Can not connect\n");
                close(c_socket);
                return -1;
        }

        write(c_socket, buffer, strlen(buffer)+1);
        memset(rcvBuffer, 0, sizeof(rcvBuffer));

        while((n=read(c_socket, rcvBuffer, BUFSIZ)) > 0){
                        printf("%s", rcvBuffer);
                        memset(rcvBuffer, 0, sizeof(rcvBuffer));
        }

        close(c_socket);
        freeaddrinfo(servinfo);

}
  • λŒ€λΆ€λΆ„μ˜ μ‚¬μ΄νŠΈλŠ” HTTPSλ₯Ό μš°μ„ μ μœΌλ‘œ ν™•μΈν•˜κΈ° λ•Œλ¬Έμ— 막상 νŒ¨ν‚·μ„ λ˜μ‘Œμ„ 경우 μ›ν•˜λŠ” κ²°κ³Όλ₯Ό Response ν•΄μ£Όμ§€ μ•ŠλŠ”λ‹€.
    image
  • 301 μ—λŸ¬ Moved Permanently (REDIRECTION) μ—λŸ¬κ°€ λ‚˜νƒ€λ‚œλ‹€.

HTTP둜 Request μ‹œ 응닡을 ν•΄μ£ΌλŠ” μ‚¬μ΄νŠΈ : ghttp2.org

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>

char buffer[BUFSIZ];

int main(int argc, char *argv[]){
        int status;
        struct addrinfo hints;
        struct addrinfo *servinfo, *tmp;                // κ²°κ³Όλ₯Ό μ €μž₯ν•  λ³€μˆ˜
        char host[256];
        int c_socket;
        struct sockaddr_in c_addr;
        int len;
        int i=0;
        char *ptr;

        char rcvBuffer[BUFSIZ];
        int n;

        c_socket = socket(PF_INET, SOCK_STREAM, 0);


        memset(&hints, 0, sizeof(hints));               // hints ꡬ쑰체의 λͺ¨λ“  값을 0으둜 μ΄ˆκΈ°ν™”
        hints.ai_family = AF_UNSPEC;                    // IPv4 IPv6 상관없이 κ²°κ³Ό λͺ¨λ‘ λ°˜ν™˜
        hints.ai_socktype = SOCK_STREAM;                // TCP stream sockets

        if(argc ==1){
                printf("Enter Domain\n ");
                return -1;
        }
        status = getaddrinfo(argv[1], "80", &hints, &servinfo);

        tmp = servinfo;
        getnameinfo(tmp->ai_addr, tmp->ai_addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);

        sprintf(buffer, "GET / HTTP/1.1\r\nHost: %s\r\nConnection: %s\r\nUpgrade: %s\r\nHTTP2-Settings: %s\r\n\r\n", argv[1], "Upgrade, HTTP2-Settings", "h2c", "<base64url encoding of HTTP/2 SETTINGS payload>");

        memset(&c_addr, 0, sizeof(c_addr));
        c_addr.sin_addr.s_addr = inet_addr(host);
        c_addr.sin_family = AF_INET;
        c_addr.sin_port = htons(80);


        if(connect(c_socket, (struct sockaddr *) &c_addr, sizeof(c_addr)) == -1){
                printf("Can not connect\n");
                close(c_socket);
                return -1;
        }

        write(c_socket, buffer, strlen(buffer)+1);
        memset(rcvBuffer, 0, sizeof(rcvBuffer));

        read(c_socket, rcvBuffer, 20);
        ptr = strstr(rcvBuffer, "101");
        if(ptr != NULL){
                printf("%s : HTTP/2 is enabled.\n", argv[1]);
        }
        else
                printf("%s : HTTP/2 Not Found.\n", argv[1]);

        close(c_socket);
        freeaddrinfo(servinfo);

}

κ²°κ³Ό ν™”λ©΄

image