This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the web-development category.
Last Updated: 2025-10-30
I uploaded a static website to s3 but it had a problem. When I visited the
index.html file in Chrome, the file was downloaded instead of rendered.
Inspecting the HTML headers, its Content-Type was wrong: Instead of 'text/html'
it was "Content-Type: binary/octet-stream". Thus the downloading. The fix was to
set the content-type when uploading the object to s3.
I installed DebugBar into some PHP code. To my surprise, this broke
various client-side JavaScript endpoints in development. This is because these
endpoints expected data in JSON or XML formats and then parsed them client-side.
However, DebugBar appends itself to the output from the server. This sorta
makes sense, since where else could it possibly appear, it being an
exclusively backend-installed tool?
I looked into the DebugBar features, and it knows to hide itself when it's a
JSON or XML content-type. My current JavaScript code specified nothing about
Content-Type (I was trying to be economical) so therefore the hiding was not
triggered during my XML/JSON requests.
After specifying the Content-Type headers for these requests, everything worked.
JSON post APIs often require two application/json entries: Content-Type and Accept
I had the following code:
def get(url)
  ...
  request = Net::HTTP::Get.new(url)
  # Important bit:
  request['accept'] = 'application/json'
  request['api-key'] = api_key
  response = http.request(request)
  parse_response_as_json(response)
end
def post(url, data = {})
  ...
  request = Net::HTTP::Post.new(url)
  # Important bit:
  request['accept'] = 'application/json'
  request['api-key'] = api_key
  request.body = data.to_json
  response = http.request(request)
  parse_response_as_json(response)
end
The get method worked but the post returned error 406 - "not acceptable"
This was confusing because the methods seemed symmetrical. In reality, what was missing was the "content-type" header for the POST method. Here's the fix
...
request['accept'] = 'application/json'
request['content-type'] = 'application/json'
The reason this is needed is in order for the server to know how to deal with the payload.
Note a potential confusion here: both GET and POST responses from the server will have a content type. However POST requests also have one, since the payload may be significant in size.
Always set content-type headers for requests