gopkg.in/hugelgupf/u-root.v2@v2.0.0-20180831055005-3f8fdb0ce09d/cmds/time_sos/server.go (about) 1 // Copyright 2018 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "encoding/json" 9 "fmt" 10 "html/template" 11 "io/ioutil" 12 "log" 13 "net/http" 14 15 "github.com/gorilla/mux" 16 "github.com/u-root/u-root/pkg/sos" 17 ) 18 19 const ( 20 DefHtmlPage = ` 21 <head> 22 <style> 23 table { 24 font-family: arial, sans-serif; 25 border-collapse: collapse; 26 width: 100%; 27 } 28 td, th { 29 border: 1px solid #dddddd; 30 text-align: left; 31 padding: 8px; 32 } 33 input { 34 font-size: 120%; 35 } 36 </style> 37 <script> 38 function sendAutoSet() { 39 fetch("http://localhost:{{.Port}}/auto", { 40 method: 'Post' 41 }) 42 .then(r => r.json()) 43 .then( s => { 44 if (s !== null) { 45 alert(s.Error); 46 window.location.reload(); 47 } 48 else { 49 window.location.reload(); 50 } 51 }) 52 .catch(err => alert(err)) 53 } 54 55 function sendManSet() { 56 d = document.getElementById("date_field").value 57 t = document.getElementById("time_field").value 58 fetch("http://localhost:{{.Port}}/manual", { 59 method: 'Post', 60 headers: { 61 'Accept': 'application/json', 62 'Content-Type': 'application/json' 63 }, 64 body: JSON.stringify({ 65 Date: d, 66 Time: t 67 }) 68 }) 69 .then(r => r.json()) 70 .then( s => { 71 if (s !== null) { 72 alert(s.Error); 73 window.location.reload(); 74 } 75 else { 76 window.location.reload(); 77 } 78 }) 79 .catch(err => alert(err)) 80 } 81 82 function setOnLoad(date, time) { 83 document.getElementById("date_field").setAttribute("value", date) 84 document.getElementById("time_field").setAttribute("value", time) 85 } 86 </script> 87 </head> 88 <body onload="setOnLoad({{.Date}}, {{.Time}})"> 89 <h1>System Time Settings</h2> 90 <table style="width:100%"> 91 <tr> 92 <td><input type="date" id="date_field"></td> 93 <td><input type="time" id="time_field"></td> 94 <td><input type="submit" id="button" value="Auto-Set" onclick=sendAutoSet()></td> 95 </tr> 96 <tr> 97 <td colspan="3"><input type="submit" id="button" value="Save" onclick=sendManSet()></td> 98 </tr> 99 </table> 100 </body> 101 ` 102 ) 103 104 type TimeServer struct { 105 service *TimeService 106 } 107 108 var ( 109 Port uint 110 ) 111 112 func (ts *TimeServer) displayStateHandle(w http.ResponseWriter, r *http.Request) { 113 ts.service.Update() 114 timeData := struct { 115 Date string 116 Time string 117 Port uint 118 }{ts.service.Date, ts.service.Time, Port} 119 var tmpl *template.Template 120 file, err := ioutil.ReadFile(sos.HTMLPath("time.html")) 121 if err == nil { 122 html := string(file) 123 tmpl = template.Must(template.New("SoS").Parse(html)) 124 } else { 125 tmpl = template.Must(template.New("SoS").Parse(DefHtmlPage)) 126 } 127 tmpl.Execute(w, timeData) 128 } 129 130 func (ts *TimeServer) autoHandle(w http.ResponseWriter, r *http.Request) { 131 if err := ts.service.AutoSetTime(); err != nil { 132 log.Printf("error: %v", err) 133 w.WriteHeader(http.StatusInternalServerError) 134 json.NewEncoder(w).Encode(struct{ Error string }{fmt.Sprintf("Unable to set time. Are you online?")}) 135 return 136 } 137 json.NewEncoder(w).Encode(nil) 138 } 139 140 type TimeJsonMsg struct { 141 Date string 142 Time string 143 } 144 145 func (ts *TimeServer) manHandle(w http.ResponseWriter, r *http.Request) { 146 var msg TimeJsonMsg 147 decoder := json.NewDecoder(r.Body) 148 defer r.Body.Close() 149 if err := decoder.Decode(&msg); err != nil { 150 log.Printf("error: %v", err) 151 w.WriteHeader(http.StatusBadRequest) 152 json.NewEncoder(w).Encode(struct{ Error string }{err.Error()}) 153 return 154 } 155 if err := ts.service.ManSetTime(msg); err != nil { 156 log.Printf("error: %v", err) 157 w.WriteHeader(http.StatusInternalServerError) 158 json.NewEncoder(w).Encode(struct{ Error string }{err.Error()}) 159 return 160 } 161 json.NewEncoder(w).Encode(nil) 162 } 163 164 func (ts *TimeServer) buildRouter() *mux.Router { 165 r := mux.NewRouter() 166 r.HandleFunc("/", ts.displayStateHandle).Methods("GET") 167 r.HandleFunc("/auto", ts.autoHandle).Methods("POST") 168 r.HandleFunc("/manual", ts.manHandle).Methods("POST") 169 r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(http.Dir(sos.HTMLPath("css"))))) 170 return r 171 } 172 173 // Start opens the server at localhost:{port}, where port is provided automatically 174 // by the SoS. 175 func (ts *TimeServer) Start() { 176 listener, port, err := sos.GetListener() 177 if err != nil { 178 log.Fatalf("error: %v", err) 179 } 180 Port = port 181 fmt.Println(sos.StartServiceServer(ts.buildRouter(), "time", listener, Port)) 182 } 183 184 // NewTimeServer creates a server with the given TimeService. 185 func NewTimeServer(service *TimeService) *TimeServer { 186 return &TimeServer{ 187 service: service, 188 } 189 }