From 967be9e750221ab2ab783f95df79bb26d290a45e Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:07:58 +0200 Subject: add: added projects --- idvoc-2025/CommentsInteractor/main.go | 147 ++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 idvoc-2025/CommentsInteractor/main.go (limited to 'idvoc-2025/CommentsInteractor/main.go') diff --git a/idvoc-2025/CommentsInteractor/main.go b/idvoc-2025/CommentsInteractor/main.go new file mode 100644 index 0000000..9a19243 --- /dev/null +++ b/idvoc-2025/CommentsInteractor/main.go @@ -0,0 +1,147 @@ +package main + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "github.com/gorilla/handlers" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/prometheus/client_golang/prometheus/promhttp" + "io" + "log" + "net/http" + "os" + "strconv" +) + +func getenv(key, fallback string) string { + value := os.Getenv(key) + if len(value) == 0 { + return fallback + } + return value +} + +type Comment struct { + Comment string `json:"comment"` +} + +type EngineError struct { + Message string `json:"message"` + AdditionalInfo string `json:"additionalInfo"` +} + +var comments_engine_endpoint string +var ( + httpHits = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "comments_interactor_http_hits_total", + Help: "The total number of hits on a given route", + }, []string{"route", "method"}) + commentsReceived = promauto.NewCounter(prometheus.CounterOpts{ + Name: "comments_interactor_comments_received_total", + Help: "The total number of comments received (successfully posted or not)", + }) + commentsPosted = promauto.NewCounter(prometheus.CounterOpts{ + Name: "comments_interactor_comments_posted_total", + Help: "The total number of comments posted (successfully posted)", + }) +) + +func sendComment(w http.ResponseWriter, r *http.Request) { + commentsReceived.Inc() + if err := r.ParseForm(); err != nil { + fmt.Fprintf(w, "

error

ParseForm() err: %v

", err) + return + } + var comment Comment + comment.Comment = r.FormValue("comment") + if comment.Comment == "" { + fmt.Fprintf(w, "

error

Empty comment or malformed

") + return + } + obj, err := json.Marshal(comment) + if err != nil { + fmt.Fprintf(w, "

error

Empty comment or malformed

") + return + } + _, err = http.Post("http://"+comments_engine_endpoint+"/comment", "application/json", bytes.NewReader(obj)) + if err == nil { + fmt.Fprintf(w, "

Success !

Comment posted

") + commentsPosted.Inc() + } else { + fmt.Fprintf(w, "

Error

Error while trying to send a comment: %s", err) + } +} + +func showDashboard(w http.ResponseWriter, r *http.Request) { + io.WriteString(w, "

Latest comments

") + io.WriteString(w, "

") + resp, err := http.Get("http://" + comments_engine_endpoint + "/latest") + if err != nil { + log.Printf("Could not HTTP get on CommentsEngine: %s", err) + io.WriteString(w, fmt.Sprintf("Error contacting the backend, %s", err)) + } else { + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + var comments []string + err = json.Unmarshal(body, &comments) + if err != nil { + var engineError EngineError + err = json.Unmarshal(body, &engineError) + if err != nil { + log.Printf("CommentsEngine returned unexpected value: %s", err) + io.WriteString(w, fmt.Sprintf("CommentsEngine returned badly formated values, %s", err)) + } else { + io.WriteString(w, fmt.Sprintf("CommentsEngine returned an error: %s
Additional info: %s", engineError.Message, engineError.AdditionalInfo)) + } + } else { + for i, comment := range comments { + io.WriteString(w, "

comment "+strconv.Itoa(i)+"

"+comment+"

") + } + } + } + io.WriteString(w, "

") + io.WriteString(w, "

Send comment

") + io.WriteString(w, "

") +} + +func getRoot(w http.ResponseWriter, r *http.Request) { + httpHits.With(prometheus.Labels{"route": "/", "method": r.Method}).Inc() + io.WriteString(w, "CommentsInteractor") + if r.Method == http.MethodPost { + sendComment(w, r) + } + showDashboard(w, r) + io.WriteString(w, "") +} + +func sendError(w http.ResponseWriter, err error, additionalInfo string) { + w.WriteHeader(http.StatusInternalServerError) + resp := make(map[string]string) + resp["message"] = fmt.Sprint(err) + resp["additionalInfo"] = additionalInfo + jsonResp, err := json.Marshal(resp) + if err != nil { + log.Fatalf("Error happened in JSON marshal. Err: %s", err) + } + w.Write(jsonResp) +} + +func main() { + http.HandleFunc("/", getRoot) + prometheus.Unregister(prometheus.NewGoCollector()) + http.Handle("/metrics", promhttp.Handler()) + + listeningHostPort := getenv("HOST", "127.0.0.1") + ":" + getenv("PORT", "9000") + comments_engine_endpoint = getenv("COMMENTS_ENGINE_ENDPOINT", "127.0.0.1:8000") + fmt.Printf("Starting the server on %s\n", listeningHostPort) + err := http.ListenAndServe(listeningHostPort, handlers.LoggingHandler(os.Stdout, http.DefaultServeMux)) + if errors.Is(err, http.ErrServerClosed) { + fmt.Printf("server closed\n") + } else if err != nil { + fmt.Printf("error starting server: %s\n", err) + os.Exit(1) + } +} -- cgit v1.2.3