From 09f5972c52c7a7e8daa0ec2c0c14c9a8e53a26bc Mon Sep 17 00:00:00 2001 From: Riley Smith Date: Fri, 21 Jan 2022 23:18:55 -0800 Subject: [PATCH] tons of frontend stuff --- backend/.idea/.gitignore | 8 ++ backend/.idea/backend.iml | 9 ++ backend/.idea/modules.xml | 8 ++ backend/.idea/vcs.xml | 6 + backend/internal/driver/driver.go | 45 ++++++++ backend/internal/logger/logger.go | 17 +++ backend/internal/server/middleware.go | 59 ++++++++++ backend/internal/server/routes.go | 14 +++ backend/internal/server/server.go | 159 ++++++++++++++++++++++++++ 9 files changed, 325 insertions(+) create mode 100644 backend/.idea/.gitignore create mode 100644 backend/.idea/backend.iml create mode 100644 backend/.idea/modules.xml create mode 100644 backend/.idea/vcs.xml create mode 100644 backend/internal/driver/driver.go create mode 100644 backend/internal/logger/logger.go create mode 100644 backend/internal/server/middleware.go create mode 100644 backend/internal/server/routes.go create mode 100644 backend/internal/server/server.go diff --git a/backend/.idea/.gitignore b/backend/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/backend/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/backend/.idea/backend.iml b/backend/.idea/backend.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/backend/.idea/backend.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/backend/.idea/modules.xml b/backend/.idea/modules.xml new file mode 100644 index 0000000..e066844 --- /dev/null +++ b/backend/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/backend/.idea/vcs.xml b/backend/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/backend/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/backend/internal/driver/driver.go b/backend/internal/driver/driver.go new file mode 100644 index 0000000..bb7e36e --- /dev/null +++ b/backend/internal/driver/driver.go @@ -0,0 +1,45 @@ +// Copyright 2018 The Go Cloud Development Kit Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// @gilcrest - removed TLSServer interface + +// Package driver defines an interface for custom HTTP listeners. +// Application code should use package server. + +package driver + +import ( + "context" + "net/http" +) + +// Server dispatches requests to an http.Handler. +type Server interface { + // ListenAndServe listens on the TCP network address addr and then + // calls Serve with handler to handle requests on incoming connections. + // The addr argument will be a non-empty string specifying "host:port". + // The http.Handler will always be non-nil. + // Drivers must block until serving is done (or + // return an error if serving can't occur for some reason), serve + // requests to the given http.Handler, and be interruptable by Shutdown. + // Drivers should use the given address if they serve using TCP directly. + ListenAndServe(addr string, h http.Handler) error + + // Shutdown gracefully shuts down the server without interrupting + // any active connections. If the provided context expires before + // the shutdown is complete, Shutdown returns the context's error, + // otherwise it returns any error returned from closing the Server's + // underlying Listener(s). + Shutdown(ctx context.Context) error +} diff --git a/backend/internal/logger/logger.go b/backend/internal/logger/logger.go new file mode 100644 index 0000000..b871a11 --- /dev/null +++ b/backend/internal/logger/logger.go @@ -0,0 +1,17 @@ +package logger + +import ( + "github.com/ubergeek77/tinylog" +) + +func NewLogger(lvl int, tag string) *tinylog.Logger { + // cfg contains our custom config for tinylog + cfg := tinylog.NewConfig() + cfg.LogLevel = lvl + cfg.LogPrefix = tinylog.GenerateTag(tag, tinylog.NewColor("38;5;133"), cfg) + + //initialize the instance of tinylog + lgr := tinylog.NewLogger(cfg) + + return lgr +} diff --git a/backend/internal/server/middleware.go b/backend/internal/server/middleware.go new file mode 100644 index 0000000..8ab4360 --- /dev/null +++ b/backend/internal/server/middleware.go @@ -0,0 +1,59 @@ +package server + +import ( + "github.com/justinas/alice" + "github.com/qpixel/tlogbuilder" + "github.com/qpixel/tloghttp" + "net/http" + "time" +) + +// MIT License +// +//Copyright (c) 2017 Dan Gillis +// +//Permission is hereby granted, free of charge, to any person obtaining a copy +//of this software and associated documentation files (the "Software"), to deal +//in the Software without restriction, including without limitation the rights +//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +//copies of the Software, and to permit persons to whom the Software is +//furnished to do so, subject to the following conditions: +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. + +// LoggerChain returns a middleware chain (via alice.Chain) +// initialized with all the standard middleware handlers for logging. The logger +// will be added to the request context for subsequent use with pre-populated +// fields, including the request method, url, status, size, duration, remote IP, +// user agent, referer. A unique Request ID is also added to the logger, context +// and response headers. +func (s *Server) loggerChain() alice.Chain { + ac := alice.New(tloghttp.NewHandler(s.logger), + tloghttp.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) { + tlogbuilder.CreateBuilder(tloghttp.FromRequest(r)). + Info(). + Str("method", r.Method). + Stringer("url", r.URL). + Int("status", status). + Int("size", size). + Dur("duration", duration). + Msg("request logged"). + Build() + }), + tloghttp.RemoteAddrHandler("remote_ip"), + tloghttp.UserAgentHandler("user_agent"), + tloghttp.RefererHandler("referer"), + //tloghttp.RequestIDHandler("request_id", "Request-Id"), + ) + + return ac +} diff --git a/backend/internal/server/routes.go b/backend/internal/server/routes.go new file mode 100644 index 0000000..a7064d9 --- /dev/null +++ b/backend/internal/server/routes.go @@ -0,0 +1,14 @@ +package server + +import "net/http" + +const ( + contentTypeHeaderKey string = "Content-Type" + appJSONContentTypeHeaderVal string = "application/json", +) + +func (s *Server) routes() { + s.router.Handle("/", func(http.ResponseWriter, *http.Response) { + + }) +} diff --git a/backend/internal/server/server.go b/backend/internal/server/server.go new file mode 100644 index 0000000..cb53caf --- /dev/null +++ b/backend/internal/server/server.go @@ -0,0 +1,159 @@ +// Copyright 2018 The Go Cloud Development Kit Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// @QPixel edits - I have made a copy of the go-api-basic server code and made +// the following changes: +// +// - removed zerolog dependency + +package server + +import ( + "context" + "errors" + "github.com/gorilla/mux" + "github.com/qpixel/watchtogether/internal/driver" + "github.com/ubergeek77/tinylog" + "io" + "net/http" + "time" +) + +const pathPrefix = "/api" + +// Server represents an HTTP server +type Server struct { + router *mux.Router + driver driver.Server + + logger *tinylog.Logger + + Addr string + + // Authorization + + // Services +} + +//type LoggerService interface { +// Read() logger.LoggerResponse +// +//} + +// SvrParams is the set of configuration parameters for a Server +type SvrParams struct { + // Logger is used for the server logging + Logger *tinylog.Logger + + // Driver serves HTTP requests + Driver driver.Server +} + +// NewServerParams is an initializer for ServerParams +func NewServerParams(lgr *tinylog.Logger, d driver.Server) *SvrParams { + options := &SvrParams{ + Logger: lgr, + Driver: d, + } + return options +} + +// NewServer initializes a new Server and registers +// routes to the router mux +// todo add error checking +func NewServer(r *mux.Router, params *SvrParams) (*Server, error) { + s := &Server{router: r} + s.logger = params.Logger + s.driver = params.Driver + + return s, nil +} + +func (s *Server) ListenAndServe() error { + if s.Addr == "" { + return errors.New("server Addr is empty") + } + if s.router == nil { + return errors.New("server router is nil") + } + if s.driver == nil { + return errors.New("server driver is nil") + } + s.logger.Infof("server is listening on %s", s.Addr) + return s.driver.ListenAndServe(s.Addr, s.router) +} + +// Shutdown will gracefully shut down the server without interrupting any active connections +func (s *Server) Shutdown(ctx context.Context) error { + if s.driver == nil { + return nil + } + return s.driver.Shutdown(ctx) +} + +// Driver implements the driver.Server interface. The zero value is a valid http.Server +type Driver struct { + Server http.Server +} + +// NewDriver intializes a Driver with http.Server using default timeouts +func NewDriver() *Driver { + return &Driver{ + Server: http.Server{ + ReadTimeout: 30 * time.Second, + WriteTimeout: 30 * time.Second, + IdleTimeout: 120 * time.Second, + }, + } +} + +// ListenAndServe sets the address and handler on Driver's http.Server +func (d *Driver) ListenAndServe(addr string, h http.Handler) error { + d.Server.Addr = addr + d.Server.Handler = h + return d.Server.ListenAndServe() +} + +// Shutdown gracefully shuts down the server without interrupting any active connections, +// by calling Shutdown on Driver's http.Server +func (d *Driver) Shutdown(ctx context.Context) error { + return d.Server.Shutdown(ctx) +} + +// NewMuxRouter initializes a gorilla/mux router and +// adds the /api subroute to it +func NewMuxRouter() *mux.Router { + // initializer gorilla/mux router + r := mux.NewRouter() + + // send Router through PathPrefix method to validate any standard + // subroutes you may want for your APIs. e.g. I always want to be + // sure that every request has "/api" as part of its path prefix + // without having to put it into every handle path in my various + // routing functions + s := r.PathPrefix(pathPrefix).Subrouter() + + return s +} + +func decoderErr(err error) error { + switch { + case err == io.EOF: + return errors.New("request body cannot be empty") + case err == io.ErrUnexpectedEOF: + return errors.New("malformed json") + case err != nil: + return err + } + return nil +}