데보션앱 소개페이지 바로가기
로그인 선택

신고하기

CLOSE
신고사유 (대표 사유 1개)
상세내용 (선택)
0/200
  • 신고한 게시글은 더 이상 보이지 않습니다.
  • 이용약관과 운영정책에 따라 신고사유에 해당하는지 검토 후 조치됩니다.
  • 허위 신고인 경우, 신고자의 서비스 이용이 제한될 수 있으니 유의하시어 신중하게 신고해 주세요.
(이 회원이 작성한 모든 댓글과 커뮤니티 게시물이 보이지 않고, 알림도 오지 않습니다.)

미리보기

커뮤니티

      1,234

      badge 23.06.15

      글 등록

      카테고리를 선택해주세요.

      DEVOTEE를 활성화 시키면
      지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.

      버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.

      임시저장함에 저장되었습니다. 저장일시 : 2022.5.17 14:29:08

      임시저장함

      제목을 선택하시면 이어서 작성이 가능하며,
      최대 20건까지 저장합니다.
      컨텐츠 유형, 제목, 저장일시, 삭제로 이뤄진 임시저장 목록
      컨텐츠 유형 제목 저장일 삭제

      데보션 블로그 게재 요청

      CLOSE
      • *
      • *

      본인인증

      효율적인 데보션 서비스 이용 및
      고객님의 소중한 개인정보보호를 위해
      본인인증을 진행해주세요. 본인인증 미 진행 시 로그인이 제한됩니다.
      본인인증 실패

      본인인증 로그인에 실패하였습니다.
      회원이 아니시거나 본인인증 등록이
      완료되지 않은 사용자입니다.

      회원정보 연결

      [네트워크] Raw HTTP Message 확인하기

      Teus 23.10.11
      2,722 18 0
      DEVOTEE 요약
      Python의 소켓(Socket)을 활용해 웹 프로그래밍 시 HTTP Raw 메시지를 확인하는 방법을 소개하고 있습니다. HTTP 통신 과정에서 서버가 받은 Raw HTTP 메시지를 Python의 Socket 라이브러리로 구조화하고 이를 웹 브라우저로 확인할 수 있습니다. 또한, Python과 Java의 Requests 패키지를 사용해 Post 메소드로 Data와 Json 등을 보낼 때 생성되는 HTTP 메시지의 차이를 확인하고 이를 이용해 서버 설정을 조정하는 방법을 제시하고 있습니다.
      DEVOTEE 추천 블로그

      안녕하세요. Teus입니다.


      이번에는 Python의 Socket을 활용해서 HTTP Raw Msg를 확인하는 방법에 대해서 다룹니다.


      1. HTTP 통신

      예전부터 requests 패키지등을 파내면서 결국 HTTP 통신은 아래처럼 흘러가게 됩니다.


      image.png


      예전 Requests Library를 통해서 Requests 패키지 내부적으로 Socket을 이용해서 HTTP Msg를 보내는것을 알아 보았습니다. (링크)

      이때 Request HTTP Msg를 수령하는 부분은 대부분 웹프래임워크(Flask, FastAPI, Django...)가 담당하고 있습니다.

      때문에 서버가 받아들인 Raw HTTP Msg를 확인하기 어려운 부분이 있습니다.

      이때 위 구조를 알고 있으면 손쉽게 Raw HTTP Msg를 확인할 수 있습니다.


      2. Python의 Socket

      Python의 경우 socket Library를 통해서 Raw Level 통신을 지원합니다.

      이때 무한루프를 돌면서 받아들이는 모든 I/O를 받는 서버를 아래처럼 구축할 수 있습니다.

      import socket
      
      host = ''
      port = 22220
      backlog = 10
      size = 2048*2
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.bind((host,port))
      s.listen(backlog)
      while 1:
          client, address = s.accept()    
          data = client.recv(size)    
          if data:
              #Data를 Byte String으로 들어오기 때문에
              #내부에서 받아들인 문자를 Decoding
              ret = data.decode()
              for i in ret.split(r"\r\n"):
                  print(i)        
              client.send(data)
          print("End Of HTTP\r\n")
          client.close()

      위 코드를 실행하고, 웹브라우저를 통해서 http://loaclhost:22220으로 접근할 경우


      아래처럼 웹브라우저가 어떤 Request Msg를 보냈는지 확인할 수 있습니다.

      image.png

      이제 위 코드를 사용해서 Python Requests와 Java의 Requests 패키지를 비교해 보겠습니다.


      3. Python을 활용해서 request Post Msg보내보기

      requests 패키지를 사용할 때 Post method의 경우 다양한 Data를 Body에 담아서 보낼 수 있습니다.

      이때 Python의 requests package를 잠시 살펴볼가요?

      출처

      def post(url, data=None, json=None, **kwargs):
          r"""Sends a POST request.
      
          :param url: URL for the new :class:`Request` object.
          :param data: (optional) Dictionary, list of tuples, bytes, or file-like
              object to send in the body of the :class:`Request`.
          :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
          :param \*\*kwargs: Optional arguments that ``request`` takes.
          :return: :class:`Response <Response>` object
          :rtype: requests.Response
          """
      
          return request("post", url, data=data, json=json, **kwargs)

      실제 HTTP Msg를 보지 않았던 사용자는 여기서 data와 json이 도대체 어떤 차이인지 알기 어렵습니다.

      결국 둘다 data를 body에 담아서 보내는구나 정도만 알 수 있습니다.

      이제 그러면 아래 두 코드를 통해서 HTTP Msg가 어떻게 만들어지는지 볼까요?

      import requests
      import json
      
      my_dt = {
              "python" : "easy",
              "java" : "hard"        
          }
      requests.post("http://localhost:22220", data = my_dt)
      requests.post("http://localhost:22220", json = my_dt)

      image.png

      결과를 보면, data에 첨부했을 경우 query string형태로 key1=value1&key2=value2 형태로 serialize 되어 전달되는 것을 볼 수 있습니다.

      반면 json으로 설정할 경우 body에서 json 형태를 유지하면서 데이터를 보내는것을 볼 수 있으며

      Content-Type header가 application/json으로 변경되는것을 볼 수가 있습니다.

      그럼 이때 data와 json두가지를 모두 설정할 경우도 한번 살펴보겠습니다.

      import requests
      import json
      
      my_dt1 = {
              "python" : "easy",
              "java" : "hard"        
          }
      my_dt2 = {
              "javascript" : "easy",
              "typescript" : "hard"        
          }
      requests.post("http://localhost:22220", data = my_dt1, json = my_dt2)

      image.png

      이 경우 json에 설정된 내용은 무시가 되고, data로 설정된 parameter만 살아남는것을 볼 수 있습니다.

      마지막으로 requests package에서 params라는 매개변수를 지원합니다.

      결국 params, data, json 모두 data를 캐리할 수 있는것을 예상할 수 있으니

      생성되는 HTTP Msg가 다르기 때문에 서버에서 어떤 HTTP Msg가 도착하는지 알아야 합니다.

      import requests
      import json
      
      my_dt = {
              "python" : "easy",
              "java" : "hard"        
          }
      requests.post("http://localhost:22220", params = my_dt)

      image.png

      확인을 해 보면 위와같이 body에 data가 있는것이 아니라 url부분에 query string으로 data가 추가되는것을 볼 수 있습니다.

      (원래 get만 이런식으로 data를 보내지만, post도 위와같이 params를 추가하여 보내는것이 가능 합니다)


      4. Java를 사용해서 request Post Msg보내보기

      다양한 언어로 만들어진 Client를 운용하기 위해서는 HTTP Msg를 동일하게 보낸주는것이 중요합니다.

      위와같이 HTTP Msg를 확인할 수 있게되면 다양한 언어에서 requests를 테스트하기 용이해집니다.

      모든 언어에서 Requests 패키지가 있지 않기때문에

      필요한 언어에서 필요한 패키지를 찾아서 테스트를 해야 할탠데요

      이때 parameter마다 어떻게 HTTP Msg가 바뀌는지 손쉽게 확인할 수 있게 됩니다.

      아래는 Java의 apache http를 사용해서 request를 보내고

      그 결과를 Raw HTTP Msg로 확인한 모습 입니다.

      package org.example;
      import org.apache.http.HttpResponse;
      import org.apache.http.NameValuePair;
      import org.apache.http.client.entity.UrlEncodedFormEntity;
      import org.apache.http.client.methods.HttpPost;
      import org.apache.http.impl.client.CloseableHttpClient;
      import org.apache.http.impl.client.HttpClients;
      import org.apache.http.message.BasicNameValuePair;
      
      
      import java.util.ArrayList;
      
      public class Main {
          public static void main(String[] args) {
              CloseableHttpClient client = HttpClients.createDefault();
              ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
              params.add(new BasicNameValuePair("Python", "easy"));
              params.add(new BasicNameValuePair("Java", "hard"));
              try {
                  HttpPost post = new HttpPost("http://localhost:22220");
                  post.setHeader("Content-Type", "application/x-www-form-urlencoded");
                  post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
                  HttpResponse response = client.execute(post);
              } catch (Exception e) {
                  System.err.println(e);
              }
          }
      }

      image.png


      이제 이 방법을 할용해서 어떻게 Client <-> Server설계를 할지 충분한 팁이 되셨을거라고 생각합니다😀


      감사합니다!

      댓글 0

      DEVOTEE를 활성화 시키면
      지금 작성한 댓글에 AI가 댓글을 달아줍니다.

      Teus 님의 최신 블로그

      더보기

      DEVOTEE 추천 블로그

      동영상 기고하기