aboutsummaryrefslogtreecommitdiff
path: root/apid
diff options
context:
space:
mode:
authorroot <sina@snix.ir>2022-01-13 13:47:30 +0000
committerroot <sina@snix.ir>2022-01-13 13:47:30 +0000
commit4039849464722c1ddadcacd136ae7e2f59835d63 (patch)
treec1a2eff7406edef94f5805bdfae8149b08f1d0d2 /apid
snix mirror
Diffstat (limited to 'apid')
-rwxr-xr-xapid/api.pdfbin0 -> 49211 bytes
-rw-r--r--apid/apid.go251
-rw-r--r--apid/const.go56
-rw-r--r--apid/dbmid.go69
4 files changed, 376 insertions, 0 deletions
diff --git a/apid/api.pdf b/apid/api.pdf
new file mode 100755
index 0000000..a743708
--- /dev/null
+++ b/apid/api.pdf
Binary files differ
diff --git a/apid/apid.go b/apid/apid.go
new file mode 100644
index 0000000..bc46f14
--- /dev/null
+++ b/apid/apid.go
@@ -0,0 +1,251 @@
+// Copyright 2021 SNIX LLC sina@snix.ir
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package apid
+
+import (
+ "context"
+ "encoding/json"
+ "goshkan/ntcp"
+ "goshkan/opts"
+ "goshkan/rgdb"
+ "goshkan/rgxp"
+ "net/http"
+ "regexp"
+)
+
+type ApiHandler struct {
+ database *rgdb.MariaSQLDB
+}
+
+type apiMiddRegex struct {
+ ctx context.Context
+ err chan error
+ dch chan interface{}
+}
+
+func newapiListRegex(c context.Context) *apiMiddRegex {
+ var err, dch = make(chan error), make(chan interface{})
+ return &apiMiddRegex{ctx: c, err: err, dch: dch}
+}
+
+func NewApid(sqlhandler *rgdb.MariaSQLDB) *ApiHandler {
+ return &ApiHandler{database: sqlhandler}
+}
+
+func newHTTPServer(router *http.ServeMux) *http.Server {
+ return &http.Server{
+ Addr: opts.Settings.ApiAdd,
+ Handler: router,
+ ReadTimeout: writeTime,
+ WriteTimeout: readxTime,
+ MaxHeaderBytes: maxHXSize,
+ }
+}
+
+func (pr *ApiHandler) Run() {
+ router := http.NewServeMux()
+ router.HandleFunc(rootShoPDF, pr.rootHandleFX)
+ router.HandleFunc(urlListAll, pr.listAllRegex)
+ router.HandleFunc(addNewREGX, pr.addNewRegexp)
+ router.HandleFunc(deleteREGX, pr.deleteRegexp)
+
+ opts.APISRV(startAPID, opts.Settings.ApiAdd)
+
+ defer pr.database.Handler.Close()
+ opts.APIERR(newHTTPServer(router).ListenAndServe())
+
+}
+
+func (pr *ApiHandler) rootHandleFX(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path != rootShoPDF {
+ httpError(w, r, http.StatusBadRequest)
+ return
+ }
+ if r.Method != http.MethodGet {
+ httpError(w, r, http.StatusMethodNotAllowed)
+ return
+ }
+ w.WriteHeader(http.StatusOK)
+ w.Write(embedPDF)
+}
+
+func (pr *ApiHandler) listAllRegex(w http.ResponseWriter, r *http.Request) {
+ opts.APIDBG(dbugNewRq, r.RemoteAddr, r.RequestURI)
+ if r.URL.Path != urlListAll {
+ httpError(w, r, http.StatusBadRequest)
+ return
+ }
+
+ if r.Method != http.MethodGet {
+ httpError(w, r, http.StatusMethodNotAllowed)
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), dbMiddleCTX)
+ defer cancel()
+
+ middle := newapiListRegex(ctx)
+ go middle.loadAllRegexCTX(pr.database)
+
+ select {
+ case err := <-middle.err:
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusInternalServerError)
+ w.Write([]byte(err.Error()))
+
+ case dba := <-middle.dch:
+ httpOKLog(w, r, dba.(rgdb.RegexList))
+
+ case <-r.Context().Done():
+ opts.APIDBG(ctxIsDone, r.RemoteAddr, r.RequestURI)
+ }
+
+}
+
+func (pr *ApiHandler) addNewRegexp(w http.ResponseWriter, r *http.Request) {
+ opts.APIDBG(dbugNewRq, r.RemoteAddr, r.RequestURI)
+ if r.URL.Path != addNewREGX {
+ httpError(w, r, http.StatusBadRequest)
+ return
+ }
+
+ if r.Method != http.MethodPost {
+ httpError(w, r, http.StatusMethodNotAllowed)
+ return
+ }
+
+ r.Body = http.MaxBytesReader(w, r.Body, MaxBDSise)
+ var input rgdb.RegStruct
+ dec := json.NewDecoder(r.Body)
+ dec.DisallowUnknownFields()
+ if err := dec.Decode(&input); err != nil {
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(err.Error()))
+ return
+ }
+
+ if len(input.Regex) < 1 {
+ opts.APIDBG(errRgISZero, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(errRgISZero))
+ return
+ }
+
+ if _, err := regexp.Compile(input.Regex); err != nil {
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(err.Error()))
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), dbMiddleCTX)
+ defer cancel()
+
+ middle := newapiListRegex(ctx)
+ go middle.saveRegexToDB(pr.database, &input.Regex)
+
+ select {
+ case err := <-middle.err:
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusInternalServerError)
+ w.Write([]byte(err.Error()))
+
+ case <-middle.dch:
+ rgxp.AddRecompileReg(&input.Regex)
+ w.WriteHeader(http.StatusOK)
+
+ case <-r.Context().Done():
+ opts.APIDBG(ctxIsDone, r.RemoteAddr, r.RequestURI)
+ }
+}
+
+func (pr *ApiHandler) deleteRegexp(w http.ResponseWriter, r *http.Request) {
+ opts.APIDBG(dbugNewRq, r.RemoteAddr, r.RequestURI)
+ if r.URL.Path != deleteREGX {
+ httpError(w, r, http.StatusBadRequest)
+ return
+ }
+
+ if r.Method != http.MethodPost {
+ httpError(w, r, http.StatusMethodNotAllowed)
+ return
+ }
+
+ r.Body = http.MaxBytesReader(w, r.Body, MaxBDSise)
+ var input rgdb.RegStruct
+ dec := json.NewDecoder(r.Body)
+ dec.DisallowUnknownFields()
+ if err := dec.Decode(&input); err != nil {
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(err.Error()))
+ return
+ }
+
+ if input.RegID == 0 {
+ opts.APIDBG(errIdIsZero, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(errIdIsZero))
+ return
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), dbMiddleCTX)
+ defer cancel()
+
+ middle := newapiListRegex(ctx)
+ go middle.deltRegexFromDB(pr.database, input.RegID)
+
+ select {
+ case err := <-middle.err:
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusInternalServerError)
+ w.Write([]byte(err.Error()))
+
+ case regs := <-middle.dch:
+ deltRegxOK(w, r, regs.(*string))
+
+ case <-r.Context().Done():
+ opts.APIDBG(ctxIsDone, r.RemoteAddr, r.RequestURI)
+ }
+
+}
+
+func deltRegxOK(w http.ResponseWriter, r *http.Request, delreg *string) {
+ if err := rgxp.DelRecompileReg(delreg); err != nil {
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusInternalServerError)
+ w.Write([]byte(err.Error()))
+ return
+ }
+ if err := ntcp.RemoveFromMap(delreg); err != nil {
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ w.WriteHeader(http.StatusInternalServerError)
+ w.Write([]byte(err.Error()))
+ return
+ }
+
+ w.WriteHeader(http.StatusOK)
+}
+
+func httpError(w http.ResponseWriter, r *http.Request, code int) {
+ http.Error(w, http.StatusText(code), code)
+ opts.APIDBG(http.StatusText(code), r.RemoteAddr, r.RequestURI)
+}
+
+func httpOKLog(w http.ResponseWriter, r *http.Request, d rgdb.RegexList) {
+ enc := json.NewEncoder(w)
+ enc.SetIndent(jsonDefault, jsonNEWPRTX)
+ w.WriteHeader(http.StatusOK)
+ if err := enc.Encode(d); err != nil {
+ opts.APIDBG(err, r.RemoteAddr, r.RequestURI)
+ }
+}
diff --git a/apid/const.go b/apid/const.go
new file mode 100644
index 0000000..728be5a
--- /dev/null
+++ b/apid/const.go
@@ -0,0 +1,56 @@
+// Copyright 2021 SNIX LLC sina@snix.ir
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package apid
+
+import (
+ _ "embed"
+ "time"
+)
+
+const (
+ writeTime = 20 * time.Second
+ readxTime
+)
+
+const (
+ dbMiddleCTX = 15 * time.Second
+)
+
+const (
+ errIdIsZero = "err: RegID cannot be equal or less than zero"
+ errRgISZero = "err: Regex cannot be nothing or empty string"
+)
+
+const (
+ maxHXSize = 1 << 14
+ MaxBDSise = 8 << 15
+)
+
+const (
+ startAPID = "starting api service at:"
+ dbugNewRq = "http req:"
+ ctxIsDone = "ctx Done() request cancelled by user"
+)
+
+const (
+ urlListAll = "/api/all/"
+ addNewREGX = "/api/add/"
+ deleteREGX = "/api/del/"
+ rootShoPDF = "/"
+)
+
+const (
+ jsonDefault = ""
+ jsonNEWPRTX = "\x09"
+)
+
+//go:embed api.pdf
+var embedPDF []byte
diff --git a/apid/dbmid.go b/apid/dbmid.go
new file mode 100644
index 0000000..240263e
--- /dev/null
+++ b/apid/dbmid.go
@@ -0,0 +1,69 @@
+// Copyright 2021 SNIX LLC sina@snix.ir
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+package apid
+
+import (
+ "goshkan/rgdb"
+)
+
+func (pr *apiMiddRegex) errorOrCancel(err error) {
+ select {
+ case pr.err <- err:
+ case <-pr.ctx.Done():
+ }
+}
+
+func (pr *apiMiddRegex) sendOnChannel(data interface{}) {
+ select {
+ case pr.dch <- data:
+ case <-pr.ctx.Done():
+ }
+}
+
+func (pr *apiMiddRegex) loadAllRegexCTX(h *rgdb.MariaSQLDB) {
+ data, err := h.LoadAllRegex(pr.ctx)
+ if err != nil {
+ pr.errorOrCancel(err)
+ return
+ }
+ pr.sendOnChannel(data)
+
+}
+
+func (pr *apiMiddRegex) saveRegexToDB(h *rgdb.MariaSQLDB, ptrn *string) {
+ if err := h.RegexIFExist(pr.ctx, ptrn); err != nil {
+ pr.errorOrCancel(err)
+ return
+ }
+
+ if err := h.AddNewRegex(pr.ctx, ptrn); err != nil {
+ pr.errorOrCancel(err)
+ return
+ }
+
+ pr.sendOnChannel(nil)
+}
+
+func (pr *apiMiddRegex) deltRegexFromDB(h *rgdb.MariaSQLDB, regid uint) {
+ regex, err := h.GetRegexByID(pr.ctx, regid)
+ if err != nil {
+ pr.errorOrCancel(err)
+ return
+ }
+
+ if err := h.DeleteRegex(pr.ctx, regid); err != nil {
+ pr.errorOrCancel(err)
+ return
+ }
+
+ pr.sendOnChannel(regex)
+
+}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR