2

I'm trying to build an app that is a Go backend, Angular front end, hosted on Google App Engine, that forces you to /login if you don't have a session or if your session's loggedIn != 1.

I'm also trying to use the App Engine's app.yaml routing for almost everything.

I'm not sure this is possible?

Directory structure:

/myapp/app.yaml
/myapp/server/main.go
/myapp/client/(ANGULAR)

app.yaml (taken from: here ) application: myapp version: 1 runtime: go111 #api_version: go1 main: ./server

- url: /go/.* #Anything that goes to the golang app
  script: _go_app

# Routing for bundles to serve directly
- url: /((?:inline|main|polyfills|styles|vendor)\.[a-z0-9]+\.bundle\.js)
  secure: always
  redirect_http_response_code: 301
  static_files: client/app/dist/\1
  upload: client/app/dist/.*

# Routing for a prod styles.bundle.css to serve directly
- url: /(styles\.[a-z0-9]+\.bundle\.css)
  secure: always
  redirect_http_response_code: 301
  static_files: client/app/dist/\1
  upload: client/app/dist/.*

# Routing for typedoc, assets and favicon.ico to serve directly
- url: /((?:assets|docs)/.*|favicon\.ico)
  secure: always
  redirect_http_response_code: 301
  static_files: client/app/dist/\1
  upload: client/app/dist/.*

# Any other requests are routed to index.html for angular to handle so we don't need hash URLs
- url: /.*
  #secure: always
  redirect_http_response_code: 301
  static_files: client/app/dist/index.html
  upload: client/app/dist/index\.html
  #http_headers:
  #  Strict-Transport-Security: max-age=31536000; includeSubDomains
  #  X-Frame-Options: DENY

So, routes to /go would act as the api... CRUD stuff. Everything else would go to Angular.

So how could i have it check if there's a session? I doubt that's possible in the app.yaml. If a call is made NOT to /go, there's no real server to tell it if there's a session.

So, is it just not possible for me to do it this way? Would I be required to use Go's routing, so that, each call can have a session check?

Flimzy
  • 60,850
  • 13
  • 104
  • 147
Chemdream
  • 460
  • 5
  • 19

1 Answers1

3

Yes, you guess it correctly. Files / folders marked as static are served separately from your Go app (using Google's content delivery network), and as such, cannot be aware of your Go app's session IDs and states.

Is it a problem for you? Usually static files (e.g. HTML, CSS and JavaScript files) can be delivered without authorization / authentication, they don't pose a security risk.

If you don't want to make your static files "public", you have to use your Go app to serve them. Don't mark them as static, and use any of the file serving mechanism of Go's standard lib (e.g. http.FileServer(), http.ServeFile() or http.ServeContent()). Use the middleware pattern to check for the existence of a session, and if one exists, only then call the file server.

(Or implement serving static content your it on your own, and you can do whatever you want / need to in your own handlers.)

For example to serve "protected" files from Go mapped to /protected, and to have some "real" static files (served by Google automatically) mapped to /static, it could look like this:

app.yaml:

- url: /protected/.*
  script: _go_app

- url: /static
  static_dir: static

Then in your Go source you may serve the "protected" files like this:

func init() {
    fileHandler := http.StripPrefix("/protected",
        http.FileServer(http.Dir("protected")))

    http.HandleFunc("/protected/", func(w http.ResponseWriter, r *http.Request) {
        // You may check if a session exists here
        sessExists := ...

        if !sessExists {
            http.Error(w, "you must login first", http.StatusUnauthorized)
            return
        }

        // Serve the requested file:
        fileHandler.ServeHTTP(w, r)
    })
}

The above init() function registers a handler that handles paths prefixed with /protected/, and if a session exists (that logic belongs to you), it calls a file server that serves the content of the protected folder. The file served is derived from the path, the /protected prefix stripped. E.g. the path /protected/secret.txt will designate the protected/secret.txt file.

icza
  • 289,344
  • 42
  • 658
  • 630
  • How would the app.yaml look like to server static files not from golang, and the rest from golang? ie: /api/* would go to golang and /dist/whatever would be served statically from another folder? – Chemdream Apr 01 '19 at 21:59
  • @Chemdream See edit, added an example (haven't tested it). – icza Apr 01 '19 at 23:32
  • I understand how that works. However, the one thing I found is that, since all angular requests need to go through the index.html, the index.html must be served via go... I was trying to not do that. But it is what it is... – Chemdream Apr 02 '19 at 13:54