Search code examples
flutter-web

Login to Flutter web app returns flutter_service_worker.js error


When I deploy a flutter web app on a cloud ubuntu server I can see the login screen ok but on login the flutter logs show this error.

preparing port 5000 ...
Server starting on port 5000 ...
172.19.0.14 - - [18/Jun/2022 11:02:06] "GET / HTTP/1.1" 304 -
172.19.0.14 - - [18/Jun/2022 11:02:07] "GET /flutter_service_worker.js?v=1208050259 HTTP/1.1" 304 -

The go api returns this error

"OPTIONS http://api.mydomain.com/login HTTP/1.1" from 172.19.0.14:59572 - 405 0B in 36.92µs

If I run my app locally as a linux client against the same api it logs in fine so the issue is with the web browser I guess. I get the same result from either Firefox or Chrome.

Here is my flutter Dockerfile:

FROM ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive 

ENV TZ=Australia/Adelaide

RUN apt-get update 
RUN apt-get install -y apt-utils psmisc
RUN apt-get install -y curl git wget unzip libgconf-2-4 gdb libstdc++6 libglu1-mesa fonts-droid-fallback lib32stdc++6 python3
RUN apt-get clean

# download Flutter SDK from Flutter Github repo
RUN git clone https://github.com/flutter/flutter.git /usr/local/flutter

# Set flutter environment path
ENV PATH="/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin:${PATH}"

# Run flutter doctor
RUN flutter doctor

# Enable flutter web
RUN flutter channel master
RUN flutter upgrade
RUN flutter config --enable-web

# Copy files to container and build
RUN mkdir /app/
COPY . /app/
WORKDIR /app/
RUN flutter build web

# Record the exposed port
EXPOSE 5000

# make server startup script executable and start the web server
RUN ["chmod", "+x", "/app/server/server.sh"]

ENTRYPOINT [ "/app/server/server.sh"]

Here is my server.sh script

#!/bin/bash

PORT=5000

echo 'preparing port' $PORT '...'
fuser -k 5000/tcp

cd build/web/

echo 'Server starting on port' $PORT '...'
python3 -m http.server $PORT

edit: I use the chi router so I implemented the following fix to my api back end and it now works.

func router() http.Handler {

    r := chi.NewRouter()

    r.Use(middleware.RequestID)
    r.Use(middleware.Logger)
    r.Use(middleware.Recoverer)
    r.Use(middleware.URLFormat)
    r.Use(render.SetContentType(render.ContentTypeJSON))
    r.Use(cors.Handler(cors.Options{
        AllowedOrigins: []string{"https://*", "http://*"},
        // AllowOriginFunc:  func(r *http.Request, origin string) bool { return true },
        AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
        AllowedHeaders:   []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
        ExposedHeaders:   []string{"Link"},
        AllowCredentials: false,
        MaxAge:           300, // Maximum value not ignored by any of major browsers
    }))

The error still exists in my flutter logs and now I'm having issues invoking saveFile.js

Server starting on port 5000 ...
172.19.0.6 - - [12/Sep/2022 13:37:48] "GET / HTTP/1.1" 200 -
172.19.0.6 - - [12/Sep/2022 13:37:48] "GET /flutter_service_worker.js?v=2601178962 HTTP/1.1" 200 -
172.19.0.6 - - [12/Sep/2022 13:37:48] "GET /main.dart.js HTTP/1.1" 200 -
172.19.0.6 - - [12/Sep/2022 13:37:48] "GET /index.html HTTP/1.1" 200 -
172.19.0.6 - - [12/Sep/2022 13:37:48] "GET /assets/AssetManifest.json HTTP/1.1" 200 -
172.19.0.6 - - [12/Sep/2022 13:37:48] "GET /assets/FontManifest.json HTTP/1.1" 200 -
172.19.0.6 - - [12/Sep/2022 13:37:49] "GET /flutter_service_worker.js?v=2601178962 HTTP/1.1" 304 -

Solution

  • When you run with your "linux client", this "linux client" probably doesn't care about CORS, but the browser does.

    And from the error message 405 - Method not allowed it seems, that your backend behind https://api.mydomain.com is not able to handle an OPTIONS request sent by the browser. You need to add the appropriate CORS handling to that backend, ie

    • add a handler for the OPTIONS request
    • add the needed CORS headers (see docs linked above) to the answer

    Depending on your sever framework, this may also be just a setting or some readily available middleware.