Added main pages, print and order_pizzas, that interact with the API
This commit is contained in:
parent
d7b35ffffa
commit
e7d62180fe
17
README.md
17
README.md
|
@ -1 +1,18 @@
|
|||
# Scontrini Web Client
|
||||
|
||||
Golang simple http server that interfaces with Scontrini-Daemon
|
||||
|
||||
## Usage
|
||||
|
||||
Compiling
|
||||
|
||||
```sh
|
||||
$ go build
|
||||
$ chmod +x ./Scontrini-Web-Client
|
||||
```
|
||||
|
||||
Executing
|
||||
|
||||
```sh
|
||||
$ ./Scontrini-Web-Client
|
||||
```
|
||||
|
|
106
api.go
Normal file
106
api.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
var (
|
||||
printer_server_IP = net.ParseIP("127.0.0.1")
|
||||
printer_server_port = 4444
|
||||
)
|
||||
|
||||
// Commands to give to the API
|
||||
type JSONCommand interface {
|
||||
PrintCommand | PizzaCommand | GetPizzasCommand
|
||||
}
|
||||
|
||||
type PrintCommand struct {
|
||||
Command string `json:"command"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type PizzaCommand struct {
|
||||
Command string `json:"command"`
|
||||
Pizzas []Pizza `json:"pizzas"`
|
||||
}
|
||||
|
||||
type GetPizzasCommand struct {
|
||||
Command string `json:"command"`
|
||||
}
|
||||
|
||||
// What to receive from the API
|
||||
type JSONReceived interface {
|
||||
ReceivePizzas
|
||||
}
|
||||
|
||||
type ReceivePizzas struct {
|
||||
Pizzas []Pizza `json:"pizzas"`
|
||||
}
|
||||
|
||||
/**
|
||||
* All messages from and to the API must have the first 4 bytes set to represent
|
||||
* the length of the message, followed by the message itself
|
||||
*/
|
||||
func sendJSONToServer[T JSONCommand](socket *net.TCPConn, json_command T) (*net.TCPConn, error) {
|
||||
json_data, err := json.Marshal(json_command)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// in case a socket doesn't already exist create a new one
|
||||
if socket == nil {
|
||||
socket, err = net.DialTCP("tcp4", nil, &net.TCPAddr{printer_server_IP, printer_server_port, ""})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// the first 4 bytes must be the length of the message
|
||||
to_send := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(to_send, uint32(len(json_data)))
|
||||
|
||||
to_send = append(to_send, json_data...)
|
||||
socket.Write([]byte(to_send))
|
||||
|
||||
return socket, nil
|
||||
}
|
||||
|
||||
func receiveJSONFromServer[T JSONReceived](socket *net.TCPConn, json_received *T) (*net.TCPConn, error) {
|
||||
var err error
|
||||
|
||||
// in case a socket doesn't already exist create a new one
|
||||
if socket == nil {
|
||||
fmt.Println("nil")
|
||||
socket, err = net.DialTCP("tcp4", nil, &net.TCPAddr{printer_server_IP, printer_server_port, ""})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// the first 4 bytes are the length of the message
|
||||
b := make([]byte, 4)
|
||||
_, err = socket.Read(b[0:])
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body_length := binary.LittleEndian.Uint32(b)
|
||||
|
||||
body := make([]byte, body_length)
|
||||
_, err = socket.Read(body[0:])
|
||||
|
||||
err = json.Unmarshal(body, json_received)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return socket, nil
|
||||
}
|
126
main.go
Normal file
126
main.go
Normal file
|
@ -0,0 +1,126 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
templates = template.Must(template.ParseFiles("templates/index.html", "templates/pizza.html"))
|
||||
)
|
||||
|
||||
type Pizza struct {
|
||||
Name string `json:"name"`
|
||||
Price int `json:"price"`
|
||||
Quantity int `json:"quantity"`
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler function for "/"
|
||||
*/
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
templates.ExecuteTemplate(w, "index.html", nil)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler function for "/print", only accepts POST requests
|
||||
*
|
||||
* Tells the API to print the text specified in its Form
|
||||
*/
|
||||
func printHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
text := r.PostFormValue("text")
|
||||
|
||||
json_command := PrintCommand{Command: "print", Text: text}
|
||||
_, err := sendJSONToServer(nil, json_command)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler function for "/pizza", only accepts POST requests
|
||||
*
|
||||
* Tells the API to print the pizza order specified in its Form
|
||||
*/
|
||||
func pizzaHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
pizzas := make([]Pizza, 0)
|
||||
|
||||
r.ParseForm()
|
||||
for key, _ := range r.Form {
|
||||
// only put in the pizzas that have a quantity bigger than 0
|
||||
if key != "submit" && r.Form[key][0] != "0" {
|
||||
quantity, _ := strconv.ParseInt(r.Form[key][0], 10, 0)
|
||||
pizzas = append(pizzas, Pizza{key, 0, int(quantity)})
|
||||
}
|
||||
}
|
||||
|
||||
json_command := PizzaCommand{Command: "pizza", Pizzas: pizzas}
|
||||
_, err := sendJSONToServer(nil, json_command)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/order_pizzas", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler function for "/order_pizzas"
|
||||
*
|
||||
* Asks the API for the list of all pizzas then returns a formatted HTML page
|
||||
*/
|
||||
func orderPizzasHandler(w http.ResponseWriter, r *http.Request) {
|
||||
json_command := GetPizzasCommand{Command: "get-pizzas"}
|
||||
socket, err := sendJSONToServer(nil, json_command)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||
return
|
||||
}
|
||||
|
||||
pizzas := ReceivePizzas{}
|
||||
_, err = receiveJSONFromServer(socket, &pizzas)
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "Error while connecting to the printer server")
|
||||
return
|
||||
}
|
||||
|
||||
templates.ExecuteTemplate(w, "pizza.html", pizzas.Pizzas)
|
||||
}
|
||||
|
||||
func main() {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.HandleFunc("/", indexHandler)
|
||||
mux.HandleFunc("/print", printHandler)
|
||||
mux.HandleFunc("/pizza", pizzaHandler)
|
||||
mux.HandleFunc("/order_pizzas", orderPizzasHandler)
|
||||
|
||||
err := http.ListenAndServe(":8080", mux)
|
||||
if errors.Is(err, http.ErrServerClosed) {
|
||||
fmt.Println("Server closed")
|
||||
} else if err != nil {
|
||||
fmt.Printf("Error starting server: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
21
templates/index.html
Normal file
21
templates/index.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scontrini</title>
|
||||
<link rel="stylesheet" href="">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>SCONTRINI</h1>
|
||||
|
||||
<h2>Cosa stampare:</h2>
|
||||
<form action="/print" method="post">
|
||||
<input name="text" id="text" type="text"></input>
|
||||
<input name="print" id="print" type="submit" value="STAMPA"></input>
|
||||
</form>
|
||||
<button><a href="/order_pizzas">Ordina le pizze</a></button>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
34
templates/pizza.html
Normal file
34
templates/pizza.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Scontrini</title>
|
||||
<link rel="stylesheet" href="">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>PIZZE</h1>
|
||||
|
||||
<form action="/pizza" method="post">
|
||||
<table id="pizzas">
|
||||
{{ range . }}
|
||||
<tr>
|
||||
<td>
|
||||
{{ .Name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ .Price }}
|
||||
</td>
|
||||
<td>
|
||||
<input name="{{ .Name }}" type="number" value="0"></input>
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</table>
|
||||
<input name="submit" id="submit" type="submit" value="ORDINA LA PIZZA"></input>
|
||||
</form>
|
||||
<button><a href="/">Stampa qualcosa</a></button>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user