Ember CLI가 nginx를 혼란스럽게 합니다

결국 공식적으로 지원되지 않는 Docker 설치 방식을 시도하고 있습니다.

이는 Ember CLI를 다른 포트에서 공유 볼륨을 사용하여 별도의 컨테이너로 실행하고, 예상대로 Rails 서버로 프록시하는 방식입니다.

불행히도, nginx 리버스 프록시를 통해 HTTPS로 완전히 접근할 때 모든 .css 자산에 대해 curl과 브라우저 모두에서 “Bad Gateway 502” 오류가 발생합니다.

Rails 서버가 이미 transfer-encoding: chunked를 추가해 두었는데도, Ember CLI가 Content-Length 헤더를 _추가_하고 있는 것으로 보입니다.

(다른 포트를 지정하여 Rails와 Ember의 응답을 각각 확인할 수 있습니다)

이것이 HTTP 1.1 프로토콜 표준을 공식적으로 위반한다고 생각하지는 않습니다(무시되어야 하므로) :

“메시지가 Transfer-Encoding 헤더 필드와 Content-Length 헤더 필드를 모두 가지고 수신되면, 후자(Content-Length)는 반드시 무시되어야 한다.”

… 하지만 nginx가 이를 받아들이지 못하고 502를 반환하며 자산을 제공하지 않으므로, 이는 무의미합니다.

localhost에서 컨테이너로 직접 curl을 사용하여 css 파일을 조회할 수는 있지만, nginx 레벨에서는 문제가 발생합니다:

upstream sent "Content-Length" and "Transfer-Encoding" headers at the same time while reading response header from upstream

Ember CLI가 이 행동을 하지 못하게 하거나 우회하는 방법에 대한 아이디어가 있으신 분 계신가요? 표준 설치에서는 통신 체인이 매우 유사할 텐데 왜 이런 문제가 발생하지 않는지 놀랍습니다.

Discourse 버전은 2.8.9입니다.

컨테이너의 헤더(간결성을 위해 일부 생략):

< content-transfer-encoding: binary
< content-type: text/css; charset=utf-8
< referrer-policy: strict-origin-when-cross-origin
< set-cookie: __profilin=p%3Dt; path=/forum; HttpOnly; SameSite=Lax
< **transfer-encoding: chunked**
< Vary: Accept, Accept-Encoding
< x-content-type-options: nosniff
< x-discourse-route: stylesheets/show
< x-download-options: noopen
< x-frame-options: SAMEORIGIN
< x-permitted-cross-domain-policies: none
< x-xss-protection: 0
< content-encoding: null
< **Content-Length: 3055**

개발 환경에서만 Ember CLI 프록시를 사용합니다. 표준 설치 환경에서는 요청이 사용자 → NGINX → Rails 순서로 전달됩니다. 이 패턴을 유지하는 것을 권장합니다. Ember CLI 구성은 프로덕션 환경 사용을 위해 설계되지 않았기 때문입니다. 설령 동작하게 만들 수 있다 해도(쉽지 않을 것입니다) 보안 및/또는 성능 관련 문제가 발생할 가능성이 높습니다.

아하, 현재 이 인스톨은 개발/운영 하이브리드 환경이라서 다음과 같은 ENV 변수가 있습니다:

RAILS_ENV: development

전단에 완전한 https와 nginx가 적용되어 있음에도 불구하고요.

하지만 ‘development’ 설정을 변경해서 동작하도록 해볼 수도 있겠네요.

네, 제 생각엔 Ember CLI는 아직 본격적인 사용에는 준비가 안 된 것 같고, 저는 “진짜” 개발 환경에서만 이걸 사용하겠습니다.

David, 그 중요한 정보를 알려주셔서 감사합니다. 덕분에 많은 시간을 절약할 수 있었습니다!

참고로, 이 이야기는 더 기이해집니다.

저는 두 개의 설치 환경을 가지고 있습니다. 둘 다 ‘개발’ 환경인데, 하나는 이 것이고, 다른 하나는 Docker가 아닌 Ubuntu 환경입니다.

Docker가 아닌 개발 서버에서 /stylesheets/에 대한 호출은 Rails 서버에서 “Transfer-Encoding: chunked” 헤더를 포함하지 않고, 대신 “Content-Length” 값을 포함하는 것을 발견했습니다… 이것이 어떻게 달라질 수 있는지 설명해 주실 수 있나요?

업데이트: https://stackoverflow.com/questions/29112728/when-does-rails-respond-with-transfer-encoding-vs-content-length 에서 설명이 가능할 것 같습니다.

그래서 스타일시트 응답에 Content-Length 헤더를 추가하는 작은 플러그인을 작성해 보려고 합니다. Transfer-Encoding: chunked 응답을 방지할 수 있는지 확인해 보기 위해서입니다.

더 간단한 방법이 있다면 알려주시면 좋겠습니다!

(참고로 이 방법은 개발 환경에서만 사용하며, 프로덕션에서는 절대 사용하지 않을 것입니다.)

이 문제에 대한 업데이트입니다.

시스템을 성공적으로 속였습니다. Content-Length 헤더를 강제하기 위해 StylesheetsController를 오버라이드하여 chunked 응답을 방지했습니다. 이를 통해 Ember CLI의 나쁜 버릇을 우회하고 nginx의 사양 미준수 문제를 피할 수 있었습니다.

이 해결책을 찾게 된 계기는, https를 사용하는 다른 Ember CLI/nginx 설정에서 Rails가 Stylesheet 응답을 chunked로 보내지 않는다는 사실을 발견한 것이었습니다. (이것이 왜 그런지 아는 분이 있을까요?) 그 후 헤더를 강제해보려고 시도했는데, 놀랍게도 성공했습니다!

이것은 개발 환경에서만 필요하므로 크게 걱정하지는 않습니다.