Post

azure 앱서비스와 리다이렉트

삐용삐용

옆 파트에서 배포하고 뭔가 에러가 난 것 같다. 증상은 자꾸 mixed content 에러가 나고, 특정 api가 http로 자꾸 요청을 보내고 있었다. 금방 해결은 되었다. 팀장님이 url 매핑이 제대로 안 되서 난 에러라고 했다. 예시를 들자면,

1
@test.get("/hello")

서버는 이런식으로 경로 매핑이 되어 있는데, 프론트에서는 요청을

1
axios.get("/hello/")

이런 식으로 던져서 난 에러라는 것이다. 이게 문제의 원인이니 앞으로는 경로를 잘 매핑하라고 지시하고 갔는데, 아무리 생각해도 근본적인 물음에 대한 답은 아닌 것 같았다.

‘그러면 로컬에서는 왜 잘 되었을까?’ ‘프로토콜은 왜 변경된걸까?’와 같은 나의 물음에 대한 정답은 아닌 것 같아서, 이리저리 생각해보며 찾아봤다.

직접 쏴보자

curl 요청을 할때 몇 가지 옵션을 주면 과정을 상세히 찍어볼 수 있다길래 gpt의 도움을 받아 한번 날려봤다. 결과는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
curl.exe -v -L -H "Authorization: Bearer 토큰" "https://..../store/category/"

### 요청 로그


* Host ....:443 was resolved.
* IPv6: (none)
* IPv4: ................
*   Trying ................:443...
* schannel: disabled automatic use of client certificate
* ALPN: curl offers http/1.1
* ALPN: server accepted http/1.1
* Connected to .... (................) port 443
* using HTTP/1.x
> GET /store/category/ HTTP/1.1
> Host: ....
> User-Agent: curl/8.10.1
> Accept: */*
> Authorization: Bearer 토큰
>
* schannel: remote party requests renegotiation
* schannel: renegotiating SSL/TLS connection
* schannel: SSL/TLS connection renegotiated
* Request completely sent off


### 응답 로그

< HTTP/1.1 307 Temporary Redirect
< Content-Length: 0
< Date: Sat, 26 Apr 2025 04:04:16 GMT
< Server: uvicorn

### uvicorn에서 자체 리다이렉트를 시킨 것 같음
### 그런데 프로토콜이 http로 변경됨

< Location: http://..../store/category   
< Set-Cookie: ARRAffinity=xx;Path=/;HttpOnly;Secure;Domain=....
< Set-Cookie: ARRAffinitySameSite=xx;Path=/;HttpOnly;SameSite=None;Secure;Domain=....
< x-ms-middleware-request-id: 00000000-0000-0000-0000-000000000000
* Ignoring the response-body
* setting size while ignoring
<

### 여기는 브라우저가 아니므로 80포트로 정상 리다이렉트, 연결

* Connection #0 to host .... left intact
* Clear auth, redirects to port from 443 to 80
* Issue another request to this URL: 'http://..../store/category'
* Host ....:80 was resolved.
* IPv6: (none)
* IPv4: ................
*   Trying ................:80...
* Connected to .... (................) port 80
* using HTTP/1.x
> GET /store/category HTTP/1.1
> Host: ....
> User-Agent: curl/8.10.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 301 Moved Permanently
< Content-Length: 0
< Date: Sat, 26 Apr 2025 04:04:16 GMT
< Location: https://..../store/category
* Ignoring the response-body
* setting size while ignoring
<
* Connection #1 to host .... left intact
* Clear auth, redirects to port from 80 to 443
* Issue another request to this URL: 'https://..../store/category'
* Re-using existing connection with host ....
> GET /store/category HTTP/1.1
> Host: ....
> User-Agent: curl/8.10.1
> Accept: */*
> Authorization: Bearer 토큰
>
* Request completely sent off
< HTTP/1.1 200 OK
< Content-Length: 160
< Content-Type: application/json
< Date: Sat, 26 Apr 2025 04:04:16 GMT
< Server: uvicorn
< Set-Cookie: ARRAffinity=xx;Path=/;HttpOnly;Secure;Domain=....
< Set-Cookie: ARRAffinitySameSite=xx;Path=/;HttpOnly;SameSite=None;Secure;Domain=....
< x-ms-middleware-request-id: 00000000-0000-0000-0000-000000000000
<

### json 결과 받아오며 끝

[{"id":"6791f33812cd7f5b4b2bc84a", .....},{"id":"6791f33812cd7f5b4b2bc84b",.....}]

* Connection #0 to host .... left intact
1
INFO: 127.0.0.1:5558 - "OPTIONS /store/category HTTP/1.1" 307 Temporary Redirect

대충 윤곽이 나왔다. uvicorn이나 fastapi 자체 정책인 것 같은데, 마지막 슬래시 제거 후 리다이렉트를 시키는 것 같다. 리다이렉트 관련 서버 로그도 확인했다.

문제는 https가 아닌 http로 리다이렉트 url을 전달해줘서 브라우저에서는 보안 에러가 난 것이다.

image

개발이나 운영 서버는 https로 떠있기 때문에 에러가 발생하지만,

image

로컬에서는 애초에 http로 띄워서 작업을 하기 때문에 리다이렉트 url의 프로토콜로 인한 에러가 발생하지 않았던 것이다. 아마 로드밸런서나 nginx같은 뭔가가 앞단에서 떠있고, 거기서 인증 처리를 하고 요청을 뒤로 넘기는 구조일 것이라 추측했다. 그러면 서버는 당연히 리다이렉트 프로토콜이 http로 넘어올 수 밖에 없었을 것이다.

문제는 우리가 azure app service를 사용하는데, 자체적으로 설정되는 인프라들이 많고 해당 리소스들에는 접근도 안되서 내 상상이 맞는지 마이크로소프트 문서들을 찾아봤다. 문서가 하도 이리저리 흩어져 있어서 일부 정보들을 취합해서 조각조각 맞추는 방식으로 진행할 수 밖에 없었다.

  • https://azure.github.io/AppService/2016/05/16/Disable-Session-affinity-cookie-(ARR-cookie)-for-Azure-web-apps.html
  • https://learn.microsoft.com/en-us/azure/architecture/web-apps/app-service/architectures/basic-web-app
  • https://learn.microsoft.com/en-us/archive/msdn-magazine/2017/february/azure-inside-the-azure-app-service-architecture

위의 자료들을 참고했고, 아마 리버스 프록시 구조가 맞는 것 같다.

image

ARR(Application Request Routing)이라는 명칭의 뭔가가 있는데 아마 로드밸런서 같고, 해당 영역은 우리가 설정 불가능 한 것 같다. 아마 azure에서 자체적으로 붙여주고 관리하는 것 같다. 번외로 그동안 ARR 쿠키 값이 뭔가 했는데 이 값으로 고정된 서버로 접속한다는 설명을 보니, 일종의 스틱키 세션 역할 같다.

image

서버 설정 옵션중에 이런 것도 있긴 한데, 이건 서버로 요청을 찔렀을 때 https로 변경하는 거고 지금 상황은 브라우저가, 그니까 서버로 요청 오기도 전에 자체적으로 막아버리는 것 같아서 크게 영향이 없을 것 같다.

굳이 코드로 뭔가 제어한다면

1
2
3
if os.getenv("ENVIRONMENT") != "dev":
    app.add_middleware(HTTPSRedirectMiddleware)
    

이렇게 로컬 개발 환경이 아니라면 리다이렉트 미들웨어를 붙여주거나,

1
uvicorn app.main:app --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem

인증서를 직접 관리하면서 실행 옵션에 넣어주는 방법도 있겠지만 우리 인프라에서는 불가능하고, 할 필요도 없는 방법일 것 같다. 이런거 신경 안쓰려고 사용하는 옵션이 앱서비스 아닐까 싶다.

This post is licensed under CC BY 4.0 by the author.

© . Some rights reserved.

Using the Jekyll theme Chirpy