Rails responding with 400 Bad Request in production but not in development (application/json body)

I have two rails apps that are sending data to each other via HTTP requests.

My first app sends its client data to the other app via this code:

    def sync_client_data
        Rails.logger.debug("*** Sending client data to tech app.")

        uri = URI(endpoint("clients")) # generates a URL e.g. my.api.com/clients

        Rails.logger.debug("*** Sending to URI: #{uri}")

        req = Net::HTTP::Post.new(uri, {
            'Content-Type' => 'application/json',
            'Authorization' => Rails.application.config.tech_app_api_key

        req.body = Client.all.to_json(include: :locations)

        res = Net::HTTP.start(uri.hostname, uri.port) do |http|

        Rails.logger.debug("*** Response: #{res}") # in production the response is: #<Net::HTTPBadRequest:0x000055b70cd18788>

        return redirect_to service_orders_path

In development, there is no error. The other app receives the JSON data just fine, and is able to process it, do things with it, etc.

In production however, the app on the receiving end just responds with 400 bad request.

The receiving end looks like this:

class Api::ClientsController < ApiController
    def create
        Rails.logger.debug("Received request to sync client data.")

        params["_json"].each do |client_json|
            # do stuff...

I don’t even see the debug output in the logs that should say “Received request to sync client data.”

A bit stumped as to how I’m going to debug this.

I found this URL with a possible solution: Catching Invalid JSON Parse Errors with Rack Middleware

I tried putting this code in config/initializers/catch_json_parse_errors_middleware.rb:

class CatchJsonParseErrors
    def initialize(app)
        @app = app
    def call(env)
            Rails.logger.debug("*** And here we are... @app.call(env)") # this gets called
        rescue ActionDispatch::ParamsParser::ParseError => error
            Rails.logger.debug("*** And here we are... ParseError") # this never gets called
            if env['CONTENT_TYPE'] =~ /application\/json/
                error_output = "There was a problem in the JSON you submitted: #{error.class}"
                return [
                    400, { "Content-Type" => "application/json" },
                    [ { status: 400, error: error_output }.to_json ]
                raise error

Rails.application.config.middleware.insert_before Rack::Head, CatchJsonParseErrors

So it looks like this “bad request” error isn’t related to JSON.

I figured out what the problem was.

        res = Net::HTTP.start(uri.hostname, uri.port) do |http|

        Rails.logger.debug("*** Response Body: #{res.read_body}")
D, [2021-04-15T16:26:35.590303 #3111646] DEBUG -- : [b8a9545c-08c7-41df-b70e-708152eaad0e] *** Response Body: <html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>

All because I didn’t set use_ssl flag on my Net::HTTP.start() call.