ID로 게시글을 업데이트할 때 500 내부 서버 오류 발생

Reverse engineer the Discourse API 를 읽고 따라 해보았으며, 엔드포인트가 실제로는 /posts/{id}.json이 아니라 /posts/{id}임을 발견했습니다. 하지만 두 가지 모두 시도해 보았습니다.

Docker에서 Discourse를 실행 중입니다. 아래 Python 코드는 500 내부 서버 오류를 반환하며, 제가 꽤 막혀 있는 상태입니다. 다른 읽기 작업(토픽 및 게시글 가져오기 등)은 정상적으로 작동합니다. API 키에는 전역 읽기 및 쓰기 권한이 있습니다.

누군가 문제의 원인을 찾아줄 수 있을까요? 만약 그렇지 않다면, 실제로 어떻게 디버깅할 수 있을까요?

endpoint = '/posts/6451'  # /posts/6451.json 도 시도해 봄
api_url = self.base_url + endpoint
headers = {'Api-Username': 'system', 'Api-Key': self.api_key}
raw = "... 여기에는 충분히 길고 유효한 마크다운이 들어갈 것입니다 ..."
data = {
    "post": {
        "raw": raw,
        "edit_reason": "API update",
        "topic_id": self.topic_id,  # 이것을 주석 처리해도 시도해 봄
        "original_text": original_raw,  # 이것을 주석 처리해도 시도해 봄
        "locale": "",  # 이것을 주석 처리해도 시도해 봄
    }
}
response = requests.put(api_url, headers=headers, data=data, timeout=10)
response.raise_for_status()

/logs에는 다음이 표시됩니다: TypeError (no implicit conversion of Symbol into Integer) app/controllers/posts_controller.rb:248:in ’ app/controllers/posts_controller.rb:248:in update' app/controllers/application_controller.rb:

app/controllers/posts_controller.rb의 248번째 줄은 여기 (제 로컬 Discourse 파일은 동일합니다)에 있으며, “raw” 문자열을 파싱하는 줄입니다. 문제의 원인을 알 수 없습니다 …

(전체 로그는 아래에 있음)

app/controllers/posts_controller.rb:248:in `[]'
app/controllers/posts_controller.rb:248:in `update'
actionpack (8.0.2.1) lib/action_controller/metal/basic_implicit_render.rb:8:in `send_action'
actionpack (8.0.2.1) lib/abstract_controller/base.rb:226:in `process_action'
actionpack (8.0.2.1) lib/action_controller/metal/rendering.rb:193:in `process_action'
actionpack (8.0.2.1) lib/abstract_controller/callbacks.rb:261:in `block in process_action'
activesupport (8.0.2.1) lib/active_support/callbacks.rb:120:in `block in run_callbacks'
app/controllers/application_controller.rb:428:in `block in with_resolved_locale'
i18n (1.14.7) lib/i18n.rb:353:in `with_locale'
app/controllers/application_controller.rb:428:in `with_resolved_locale'
activesupport (8.0.2.1) lib/active_support/callbacks.rb:129:in `block in run_callbacks'
activesupport (8.0.2.1) lib/active_support/callbacks.rb:140:in `run_callbacks'
actionpack (8.0.2.1) lib/abstract_controller/callbacks.rb:260:in `process_action'
actionpack (8.0.2.1) lib/action_controller/metal/rescue.rb:27:in `process_action'
actionpack (8.0.2.1) lib/action_controller/metal/instrumentation.rb:76:in `block in process_action'
activesupport (8.0.2.1) lib/active_support/notifications.rb:210:in `block in instrument'
activesupport (8.0.2.1) lib/active_support/notifications/instrumenter.rb:58:in `instrument'
activesupport (8.0.2.1) lib/active_support/notifications.rb:210:in `instrument'
actionpack (8.0.2.1) lib/action_controller/metal/instrumentation.rb:75:in `process_action'
actionpack (8.0.2.1) lib/action_controller/metal/params_wrapper.rb:259:in `process_action'
activerecord (8.0.2.1) lib/active_record/railties/controller_runtime.rb:39:in `process_action'
actionpack (8.0.2.1) lib/abstract_controller/base.rb:163:in `process'
actionview (8.0.2.1) lib/action_view/rendering.rb:40:in `process'
rack-mini-profiler (4.0.1) lib/mini_profiler/profiling_methods.rb:90:in `block in profile_method' 
actionpack (8.0.2.1) lib/action_controller/metal.rb:252:in `dispatch'
actionpack (8.0.2.1) lib/action_controller/metal.rb:335:in `dispatch'
actionpack (8.0.2.1) lib/action_dispatch/routing/route_set.rb:67:in `dispatch'
actionpack (8.0.2.1) lib/action_dispatch/routing/route_set.rb:50:in `serve'
actionpack (8.0.2.1) lib/action_dispatch/journey/router.rb:53:in `block in serve'
actionpack (8.0.2.1) lib/action_dispatch/journey/router.rb:133:in `block in find_routes'
actionpack (8.0.2.1) lib/action_dispatch/journey/router.rb:126:in `each'
actionpack (8.0.2.1) lib/action_dispatch/journey/router.rb:126:in `find_routes'
actionpack (8.0.2.1) lib/action_dispatch/journey/router.rb:34:in `serve'
actionpack (8.0.2.1) lib/action_dispatch/routing/route_set.rb:908:in `call'
lib/middleware/omniauth_bypass_middleware.rb:35:in `call'
rack (2.2.17) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.17) lib/rack/conditional_get.rb:40:in `call'
rack (2.2.17) lib/rack/head.rb:12:in `call'
actionpack (8.0.2.1) lib/action_dispatch/http/permissions_policy.rb:38:in `call'
lib/content_security_policy/middleware.rb:12:in `call'
lib/middleware/anonymous_cache.rb:415:in `call'
lib/middleware/csp_script_nonce_injector.rb:12:in `call'
config/initializers/008-rack-cors.rb:14:in `call'
rack (2.2.17) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.17) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/cookies.rb:706:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/callbacks.rb:31:in `block in call'
activesupport (8.0.2.1) lib/active_support/callbacks.rb:100:in `run_callbacks'
actionpack (8.0.2.1) lib/action_dispatch/middleware/callbacks.rb:30:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:31:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:32:in `call'
logster (2.20.1) lib/logster/middleware/reporter.rb:40:in `call'
lib/middleware/default_headers.rb:13:in `call'
railties (8.0.2.1) lib/rails/rack/logger.rb:41:in `call_app'
railties (8.0.2.1) lib/rails/rack/logger.rb:29:in `call'
config/initializers/100-quiet_logger.rb:20:in `call'
config/initializers/100-silence_logger.rb:29:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/request_id.rb:34:in `call'
lib/middleware/enforce_hostname.rb:23:in `call'
rack (2.2.17) lib/rack/method_override.rb:24:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/executor.rb:16:in `call'
rack (2.2.17) lib/rack/sendfile.rb:110:in `call'
rack-mini-profiler (4.0.1) lib/mini_profiler.rb:191:in `call'
lib/middleware/processing_request.rb:12:in `call'
message_bus (4.4.1) lib/message_bus/rack/middleware.rb:60:in `call'
lib/middleware/request_tracker.rb:410:in `call'
actionpack (8.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:96:in `call'
railties (8.0.2.1) lib/rails/engine.rb:535:in `call'
railties (8.0.2.1) lib/rails/railtie.rb:226:in `public_send'
railties (8.0.2.1) lib/rails/railtie.rb:226:in `method_missing'
rack (2.2.17) lib/rack/urlmap.rb:74:in `block in call'
rack (2.2.17) lib/rack/urlmap.rb:58:in `each'
rack (2.2.17) lib/rack/urlmap.rb:58:in `call'
unicorn (6.1.0) lib/unicorn/http_server.rb:634:in `process_client'
unicorn (6.1.0) lib/unicorn/http_server.rb:739:in `worker_loop'
unicorn (6.1.0) lib/unicorn/http_server.rb:547:in `spawn_missing_workers'
unicorn (6.1.0) lib/unicorn/http_server.rb:143:in `start'
unicorn (6.1.0) bin/unicorn:128:in `<top (required)>'
vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `load'
vendor/bundle/ruby/3.3.0/bin/unicorn:25:in `<main>'

죄송합니다. 혹시 다른 분들도 같은 문제를 겪을 수 있으니 참고용으로 남겨둡니다.

실제로 전송된 HTTP 요청을 디버깅해 보니, Python이 PUT 데이터를 "post=raw&post=edit_reason" 형태로 보내고 있었습니다. requests.put() 호출에서 data=datajson=data로 교체하니 문제가 해결되었습니다.