본문 바로가기
Today I learned

Real World HTTP

by soheemon 2020. 6. 15.
본 POST는 Real World HTTP를 읽고 정리한 내용입니다. 

 

- form의 GET의경우 request body가 아니라 query로서 URL에 부여된다.[RFC 1866] 반면 POST의 경우 request body영역에 저장된다.

 

- HTML의 form에서는 옵션으로 멀티파트 폼 형식이라는 인코딩 타입을 선택할 수 있다. [RFC1867]

 

- application/x-www-form-urlencoded: &으로 분리되고, "=" 기호로 값과 키를 연결하는 key-value tuple로 인코딩되는 값이다. 

반면 multipart/form-data는 항목마다 추가 메타정보를 태그로 가질 수 있다. 파일명/파일종류/파일내용

POST /foo HTTP/1.1
Content-Length: 68137
Content-Type: multipart/form-data; boundary=---------------------------974767299852498929531610575
Content-Disposition: form-data; name="description"
---------------------------974767299852498929531610575

some text

---------------------------974767299852498929531610575
Content-Disposition: form-data; name="myFile"; filename="foo.txt" 
Content-Type: text/plain 

(content of the uploaded file foo.txt)

---------------------------974767299852498929531610575--

- Form을 이용한 Redirect

<!DOCTYPE html>
<html>
<body onload="document.forms[0].submit()">
  <form action="리디렉트하고 싶은 곳" method="post">
    <input action="hidden" name="data" value="보내고자하는 데이터"/>
    <input type="submit" value="Continue"/>
  </form>
</body>

- 쿠키에 제약이 필요한 이유

ㄴ 클라이언트는 서버가 보낸 쿠키를 로컬스토리지에 저장하고, 같은 URL로 접속할 때 저장된 쿠키를 읽고 요청 헤더에 넣는다.

ㄴ 쿠키는 특정 서비스를 이용하는 토큰으로 이용될 때가 많다. 그래서 쿠키가 필요하지 않은 서버에 전송하는것은 보안이 위험해지기 때문이다.

ㄴ 쿠키를 보낼 서버를 제어하거나 쿠키의 수명을 설정하는 등 쿠키를 제한하는 속성이 몇가지 정의되어 있으며 HTTP 클라이언트는 이 속성을 해석해 쿠키 전송을 제어할 책임이 있다.

 

- 주요 쿠키 속성

ㄴ Domain 속성 : 클라이언트에서 쿠키를 전송할 대상 서버. 생략하면 쿠키를 발생한 서버가 된다.

ㄴ Path 속성: 클라이언트에서 쿠키를 전송할 대상 서버의 경로 생략하면 /

ㄴ Secure속성 : https로 프로토콜을 사용한 보안 접속일때만 클라이언트에서 서버로 쿠키를 전송한다. DNS해킹으로 URL을 조작하면 의도치 않은 서버에 쿠키를 전송할 위험이 있다. Secure속성을 붙이면 http접속일 때에는 브라우저가 경고를 하고 접속하지 않아 정보유출을 막게 된다.

ㄴ HttpOnly 속성 : js엔진으로부터 쿠키를 감출 수 있다. CSS등 악의적인 자바스크립트가 실행되는 보안 위험에 대한 방어가 된다.

ㄴ SameSite: 같은 출처의 도메인에만 쿠키를 전송한다.

 

- 서명된 쿠키를 이용한 세션 데이터 저장

ㄴ 예전의 세션 스토리지는 관계형 데이터베이스에 전용 테이블을 만들고, 세션관리에서 작성한 세션ID키를 이용하여 서버측에서 데이터를 관리했다.

현재 장고 1.4버전부터 기본 세션 스토리지는 쿠키를 이용해 데이터를 저장한다.

ㄴ 이 시스템에서는 변조되지 않도록 서버가 클라이언트에 전자서명된 데이터를 보낸다.

ㄴ 클라이언트가 서버로 쿠키를 재정송하면 서버는 서명을 확인한다.

ㄴ 서명하는것도 서명을 확인하는것도 서버에서 하므로 클라이언트는 열쇠를 갖지 않는다. 공개키와 비밀키 모두 서버에 있다.

 

-프록시와 게이트웨이의 차이

ㄴ 프록시: 통신 내용을 이해한다. 필요에 따라서 컨텐츠를 수정하거나 서버 대신 응답한다.

ㄴ 게이트웨이: 통신 내용을 그대로 전송한다. 내용의 수정도 불가하다. 클라이언트에서 중간에 존재하는것을 알 수 없다.

 

- HTTP 헤더를 이용한 브라우저 캐시

ㄴHTTP/1.0에서는 정적 콘텐츠 위주라서 콘텐츠가 갱신됐는지만 비교하면 충분했다.

1) 갱신 일자에 따른 캐시

Last-Modified: Wed, 08 Jun 2016 15:23:45 GMT

<!-- 웹브라우저가 캐시된 URL을 다시 읽을때는 서버에서 반환된 일시를 그대로 If-Modified-Since헤더에 넣어 요청한다. --!>

If-Modified-Since: Wed, 08 Jun 2016 15:23:45 GMT

ㄴ 캐시된 URL을 다시 읽을때 클라이언트는 서버에서 반환된 일시를 If-Modified-Since헤더에 넣어 Request를 전송한다.

ㄴ 서버는 Request 헤더에 포함된 If-Modified-Since 의 일시와 서버의 콘텐츠 일시를 비교한다.

ㄴ 변경됐으면 정상 스테이터스 코드 200OK를 반환하고, 콘텐츠를 응답 바디에 실어서 보낸다.

ㄴ 변경되지 않았으면 스테이터스 코드 304 Not Modified를 반환한다.

2) Expires

Expire 헤더에는 날짜와 시간이 들어간다. 클라이언트는 지정한 기간 내라면 캐시가 '신선'하다고 판단하고 기존에 캐시된 데이터를 사용한다. (요청을 아예 전송하지 않는다)

반면 유효기간이 지났으면 캐시가 신선하지 않다라고 판단해서 해당 콘텐츠를 서버에 다시 요청하여 캐시를 갱신한다.

 

3)ETag

날짜와 시간을 이용한 캐시 비교만으로 해결할 수 없는경우가 있다. 바로 동적으로 바뀌는 요소에 대한 캐시다.

동적으로 바뀌는 요소가 늘어날수록 어떤 날짜를 근거로 캐시의 유효성을 판단해야 하는지 결정하기가 어려워진다. 따라서 하나의 수치로 귀착시켜야 한다.

 

HTTP/1.1에서 추가된 ETag

ㄴ ETag는 순차적인 갱신 일자가 아니라 파일의 해시값으로 비교한다.

ㄴ 날짜와 시간을 이용해 확인할 때 처럼 서버는 Response헤더에 ETag헤더를 부여한다(서버렌더링 등등 끝낸 HTML파일의 해시값). 두번째 이후 다운로드시 클라이언트는 Request 헤더에 다운로드된 캐시에 들어있던 ETag값을 추가해 요청한다.

ㄴ 서버는 보내려는 파일의 ETag와 비교해서 같으면 304 Not Modified로 응답한다.

 

ㄴETag는 서버가 자유롭게 결정해서 반환할 수 있다. 해시값을 서버가 생성할 수 있다.

ㄴ 갱신일시-파일크기를 16진수로 연결

ㄴ 그 외에 inode번호도 이용했지만 서버를 병렬연결시킨경우 ID가 달라져 ETag가 바뀌므로 캐시가 낭비되는 일이 있었음

 

추가된 브라우저 캐시로직..,, 너무 스케일을 크게잡아벌임 ㅠ

4)Cashe-Control

Expires보다 우선해서 처리된다.

Response 헤더들

  • public: 같은 컴퓨터를 사용하는 복수의 사용자간 캐시 재사용을 허가한다

  • private: 같은 컴퓨터를 사용하는 다른 사용자 간 캐시를 재사용하지 않는다. 같은 URL에서 사용자마다 다른 콘텐츠가 돌아오는 경우에 이용한다

  • max-age=n: 캐시의 신선도를 초단위로 설정한다.

  • s-maxage=n : max-age와 같으나 캐시에 대한 설정값이다

  • no-cache: 캐시가 유효한지 매번 물어본다 max-age=0과 거의 같다. (랜덤값을 쿼리스트링으로 붙이는것과 유사한 동작)

  • no-store: 캐시를 사용하지 않는다

no-cache는 Pragma: no-cache와 똑같이 '캐쉬하지 않는것이 아니다' 다만 서버에 캐시가 신선한지 매번 물어볼 뿐이다. 200코드가 날아오면 콘텐츠와 캐시를 갱신하고, 304코드가 날아오면 기존에 캐시된 콘텐츠를 사용할 뿐이다.

 

4-1)Cashe-Control(2)

서버에서 프록시로 보내는 Response헤더에 사용할 수 있는 지시도 있다.

Request 헤더들

no-

댓글