1

Background:

I'm currently trying to fetch data from an endpoint from a next.js application. The backend is a simple Flask app (in development mode) with an exposed port at 5000. Nginx is acting as a reverse proxy for next and flask, as well as handling http -> https. I'm using docker compose to bring all these services together. I'm hosting all of these services on a single droplet on DigitalOcean.

I've gone through multiple iterations since going from a local dev environment (i.e. just using localhost) to deployment (https website). The errors range from 404, net::ERR_SSL_PROTOCOL_ERROR, to mixed content errors (depending on the iteration). Despite the range of errors, there is clearly something fundamental I'm missing here that's preventing fetch from working.

Code:

NGINX

server {
  listen 80;
  server_name mydomainname.com;

  location / {
    return 301 https://$host$request_uri;
  }

  location /.well-known/acme-challenge/ {
    root /var/www/certbot;
  }

}

# https traffic
server {
  listen 443 ssl;
  server_name mydomainname.com;
  add_header 'Content-Security-Policy' 'upgrade-insecure-requests';

  ssl_certificate /etc/letsencrypt/live/mydomainname.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/mydomainname.com/privkey.pem;

  location / {
    proxy_pass        http://client:3000;
    proxy_redirect    default;
    proxy_set_header  Upgrade $http_upgrade;
    proxy_set_header  Connection "upgrade";
    proxy_set_header  Host $host;
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Host $server_name;
    proxy_set_header  X-Forwarded-Proto $scheme;
  }

  location /api {
    proxy_pass        http://api:5000;
    proxy_redirect    default;
    proxy_set_header  Host $host;
    proxy_set_header  Upgrade $http_upgrade;
    proxy_set_header  Connection "upgrade";
    proxy_set_header  X-Real-IP $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Host $server_name;
    proxy_set_header  X-Forwarded-Proto $scheme;
  }
}

DOCKER

version: '3.7'

services:
  api:
    container_name: api
    build:
      context: ./api
      dockerfile: Dockerfile
    volumes:
      - './api:/usr/src/app'
    ports:
      - 5000:5000
    environment:
      - FLASK_CONFIG=development
      - FLASK_ENV=development

  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    depends_on:
      - api
      - client
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
  
  certbot:
    image: certbot/certbot
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot

  client:
    container_name: client
    build:
      context: ./client
      dockerfile: Dockerfile
    volumes:
      - './client:/usr/src/app'
      - '/usr/src/app/node_modules'
    ports:
      - 3000:3000
    environment:
      - NODE_ENV=development
      - REACT_APP_SERVICE_URL=http://localhost:8080
      - CHOKIDAR_USEPOLLING=true
    depends_on:
      - api

FLASK

@app.route('/myroute', methods=['GET'])
def my_route():
    keywords = request.args.getlist('search')

    # TRUNCATED CODE STARTS HERE THAT FORMS JSON DATA
    # ...
    # ...

    response = flask.jsonify(json)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

if __name__ == '__main__':

    app.run(port='5000')

NEXT

const fetchData = async () => {
      
      const response = await fetch(`https:mydomainname.com/api/myroute?search=${search}`)
      const json: ApiResponse = await response.json()
     
    }
// call the function
    fetchData().catch(res => {
      console.log(res)
      router.push(`/`)
    });
}

I've truncated the next and flask code so it's easier to parse.

In terms of a (short) list of things I've tried in terms of url formation in fetch:

fetch(`https:mydomainname.com/api/myroute?search=${search}`)
fetch(`http:mydomainname.com/api/myroute?search=${search}`)
fetch(`http:mydomainname.com/myroute?search=${search}`)
fetch(`https:mydomainname.com/myroute?search=${search}`)
fetch(`//mydomainname.com/myroute?search=${search}`)
juliomalves
  • 42,130
  • 20
  • 150
  • 146
Collaptic
  • 307
  • 1
  • 6
  • 16
  • 1
    Do you need to set the Flask app to `app.run(host='0.0.0.0')`, as in [Deploying a minimal flask app in docker - server connection issues](https://stackoverflow.com/questions/30323224/deploying-a-minimal-flask-app-in-docker-server-connection-issues)? – David Maze May 16 '22 at 01:21
  • I actually had host setup as 0.0.0.0 up until recently. Sounds like that might be at least one of the few errors I have going on based on the link you provided. I’ll revert the code and give it a go again. – Collaptic May 16 '22 at 01:41

0 Answers0