server.go 2.48 KB
Newer Older
Sietse Ringers's avatar
Sietse Ringers committed
1
package irmaserver
2
3
4
5
6
7

import (
	"fmt"
	"io/ioutil"
	"net/http"

8
	"github.com/go-chi/chi"
9
10
	"github.com/go-errors/errors"
	"github.com/privacybydesign/irmago"
Sietse Ringers's avatar
Sietse Ringers committed
11
12
	"github.com/privacybydesign/irmago/server"
	"github.com/privacybydesign/irmago/server/irmarequestor"
13
14
)

15
type Configuration struct {
Sietse Ringers's avatar
Sietse Ringers committed
16
	*server.Configuration
17
18
19
	Port int
}

Sietse Ringers's avatar
Sietse Ringers committed
20
var s *http.Server
21

22
23
24
// Start the server. If successful then it will not return until Stop() is called.
func Start(conf *Configuration) error {
	if err := irmarequestor.Initialize(conf.Configuration); err != nil {
25
26
27
		return err
	}

28
	router := chi.NewRouter()
29

30
31
	// Mount server for irmaclient
	router.Mount("/irma/", irmarequestor.HttpHandlerFunc("/irma/"))
32

33
34
35
36
	// Server routes
	router.Post("/create", handleCreate)
	router.Get("/status/{token}", handleStatus)
	router.Get("/result/{token}", handleResult)
37

38
	// Start server
Sietse Ringers's avatar
Sietse Ringers committed
39
40
	s = &http.Server{Addr: fmt.Sprintf(":%d", conf.Port), Handler: router}
	err := s.ListenAndServe()
41
42
43
44
	if err == http.ErrServerClosed {
		return nil // Server was closed normally
	}
	return err
45
46
47
}

func Stop() {
Sietse Ringers's avatar
Sietse Ringers committed
48
	s.Close()
49
50
}

51
52
53
func handleCreate(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
Sietse Ringers's avatar
Sietse Ringers committed
54
		server.WriteError(w, server.ErrorInvalidRequest, err.Error())
55
56
57
58
		return
	}
	request, err := parseRequest(body)
	if err != nil {
Sietse Ringers's avatar
Sietse Ringers committed
59
		server.WriteError(w, server.ErrorInvalidRequest, err.Error())
60
61
62
63
64
		return
	}

	qr, _, err := irmarequestor.StartSession(request, nil)
	if err != nil {
Sietse Ringers's avatar
Sietse Ringers committed
65
		server.WriteError(w, server.ErrorInvalidRequest, err.Error())
66
67
68
		return
	}

Sietse Ringers's avatar
Sietse Ringers committed
69
	server.WriteJson(w, qr)
70
71
72
73
74
}

func handleStatus(w http.ResponseWriter, r *http.Request) {
	res := irmarequestor.GetSessionResult(chi.URLParam(r, "token"))
	if res == nil {
Sietse Ringers's avatar
Sietse Ringers committed
75
		server.WriteError(w, server.ErrorSessionUnknown, "")
76
77
		return
	}
Sietse Ringers's avatar
Sietse Ringers committed
78
	server.WriteJson(w, res.Status)
79
80
81
82
83
}

func handleResult(w http.ResponseWriter, r *http.Request) {
	res := irmarequestor.GetSessionResult(chi.URLParam(r, "token"))
	if res == nil {
Sietse Ringers's avatar
Sietse Ringers committed
84
		server.WriteError(w, server.ErrorSessionUnknown, "")
85
86
		return
	}
Sietse Ringers's avatar
Sietse Ringers committed
87
	server.WriteJson(w, res)
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
}

func parseRequest(bts []byte) (request irma.SessionRequest, err error) {
	request = &irma.DisclosureRequest{}
	if err = irma.UnmarshalValidate(bts, request); err == nil {
		return request, nil
	}
	request = &irma.SignatureRequest{}
	if err = irma.UnmarshalValidate(bts, request); err == nil {
		return request, nil
	}
	request = &irma.IssuanceRequest{}
	if err = irma.UnmarshalValidate(bts, request); err == nil {
		return request, nil
	}
	return nil, errors.New("Invalid session type")
}