memoServerHandlerMain.go 2.87 KB
Newer Older
Jürgen Enge's avatar
Jürgen Enge committed
1
2
3
4
5
6
7
8
9
10
// This file is part of Memobase Mediaserver which is released under GPLv3.
// See file license.txt for full license details.
//
// Author Juergen Enge <juergen@info-age.net>
//
// This code uses elements from
// * "Mediaserver" (Center for Digital Matter HGK FHNW, Basel)
// * "Remote Exhibition Project" (info-age GmbH, Basel)
//

Jürgen Enge's avatar
Jürgen Enge committed
11
12
13
package memostream

import (
Jürgen Enge's avatar
Jürgen Enge committed
14
	"github.com/gorilla/mux"
Jürgen Enge's avatar
Jürgen Enge committed
15
16
17
	"net/http"
	"net/http/httputil"
	"net/url"
18
	"regexp"
Jürgen Enge's avatar
Jürgen Enge committed
19
	"strings"
Jürgen Enge's avatar
Jürgen Enge committed
20
21
)

Juergen Enge's avatar
Juergen Enge committed
22
// proxy to gifen url
Jürgen Enge's avatar
Jürgen Enge committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
func proxy(url url.URL, w http.ResponseWriter, req *http.Request) {
	// build a proxy director, which connects to our target url
	director := func(req *http.Request) {
		req.URL.Scheme = url.Scheme
		req.URL.Host = url.Host
		req.URL.Path = url.Path
		if _, ok := req.Header["User-Agent"]; !ok {
			// explicitly disable User-Agent so it's not set to default value
			req.Header.Set("User-Agent", "")
		}
	}

	// create the reverse proxy
	rp := httputil.ReverseProxy{Director: director}

	// and go for it
Jürgen Enge's avatar
Jürgen Enge committed
39
	// should we use IdleTimeoutConn? Paranoia?
Jürgen Enge's avatar
Jürgen Enge committed
40
41
42
	rp.ServeHTTP(w, req)
}

43
44
var regexpFallback = regexp.MustCompile("^fallback(.+)$")

Jürgen Enge's avatar
Jürgen Enge committed
45
46
func (ms *memoServer) mainHandler(w http.ResponseWriter, req *http.Request) {
	// remove prefix and use whole rest of url as signature
Jürgen Enge's avatar
Jürgen Enge committed
47
48
49
50
51
52
53
	vars := mux.Vars(req)
	signature, ok := vars["signature"]
	if !ok {
		ms.DoPanicf(w, http.StatusBadRequest, "no signature in url: %s", req.URL.Path)
		return
	}
	action, _ := vars["action"]
Juergen Enge's avatar
Juergen Enge committed
54
	paramstr, _ := vars["params"]
55
	params := strings.Split(paramstr, "/")
Jürgen Enge's avatar
Jürgen Enge committed
56

Juergen Enge's avatar
Juergen Enge committed
57
	subClaim := "sub"
Jürgen Enge's avatar
Jürgen Enge committed
58
59
60
	// resolve signature
	me, err := ms.resolver.resolve(signature)
	if err != nil {
61
62
63
64
65
66
67
68
69
		// check for fallback parameter only if needed
		fallback := ""
		for _, p := range params {
			if matches := regexpFallback.FindStringSubmatch(p); matches != nil {
				fallback = matches[1]
				break
			}
		}
		if fallback != "" {
Juergen Enge's avatar
Juergen Enge committed
70
			// todo: check jwt for fallback
71
72
73
74
75
			me, err = ms.resolver.resolve(fallback)
			if err != nil {
				ms.DoPanicf(w, http.StatusNotFound, "signature %v and fallback %v not found: %v", signature, fallback, err)
				return
			}
Juergen Enge's avatar
Juergen Enge committed
76
			subClaim = "fb"
77
78
79
80
		} else {
			ms.DoPanicf(w, http.StatusNotFound, "signature %v not found: %v", signature, err)
			return
		}
Jürgen Enge's avatar
Jürgen Enge committed
81
82
	}
	if me.Access != Media_Public {
Juergen Enge's avatar
Juergen Enge committed
83
		if err := CheckRequestJWT(req, ms.jwtSecret, ms.jwtAlg, signature, subClaim); err != nil {
Jürgen Enge's avatar
Jürgen Enge committed
84
85
86
87
88
			ms.DoPanicf(w, http.StatusForbidden, "Access denied: token check failed: %v", err)
			return
		}
	}

Juergen Enge's avatar
Juergen Enge committed
89
90
91
	if me.Type == "" {
		me.Type = "unknown"
	}
Juergen Enge's avatar
Juergen Enge committed
92
93
	if actions, ok := ms.actions[me.Type]; ok {
		for _, a := range actions {
94
			ok, err := a.Do(w, req, me, action, params...)
Juergen Enge's avatar
Juergen Enge committed
95
96
97
98
99
100
101
102
103
			if err != nil {
				ms.DoPanicf(w, http.StatusInternalServerError, "Cannot execute action %s on signature %s: %v", action, me.Signature, err)
				return
			}
			if ok {
				return
			}
		}
	}
Juergen Enge's avatar
Juergen Enge committed
104
	ms.DoPanicf(w, http.StatusInternalServerError, "no handler for action %s on signature %s (%v) found", action, me.Signature, me.Type)
Juergen Enge's avatar
Juergen Enge committed
105
	return
Jürgen Enge's avatar
Jürgen Enge committed
106
}