Skip to content

Commit

Permalink
Merge pull request #53 from webability-go/late-night
Browse files Browse the repository at this point in the history
v1.4.0
  • Loading branch information
metalwolf authored Aug 13, 2020
2 parents fde8e52 + 4d77655 commit 8b83f2e
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 68 deletions.
73 changes: 72 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,72 @@ func Log(ctx *assets.Context) {
```



2. "listeners" section

The listener is the thread charged to listen to a specific IP:Port on the server, with some metrics and logs.

The general syntax is:

```
"listeners": [ <LISTENER1>, <LISTENER2>, ... ]
Each listener is:
{
"name": "<NAME>",
"ip": "<IP>",
"port": "<PORT>",
"protocol": "<PROTOCOL>",
"readtimeout": <TIMEOUT>,
"writetimeout": <TIMEOUT>,
"headersize": <SIZE>,
"log": {
"sys": "<SYSLOG>",
}
}
```

Where each parameter is:

<NAME>: is the name of the listener (any string)
<IP>: is the IP to listen to. If the IP is empty "", then the server will listen to all the available IPs on the server.
<PORT>: is the port to listen to.
<PROTOCOL>: is the protocol to listen to. For now, Xamboo knows http and https only.
<TIMEOUT>: is a number between 0 and 65535, the time is in seconds.
<SIZE>: is a number between 4096 and 65535, the size is in bytes.
the <SYSLOG> is explained in the log section.

Example of a working real listeners for HTTP and HTTPS:

```
"listeners": [
{
"name": "server-http",
"ip": "10.10.10.10",
"port": "80",
"protocol": "http",
"readtimeout": 120,
"writetimeout": 120,
"headersize": 65536,
"log": {
"sys": "file:./logs/listener-http-sys.log",
}
},
{
"name": "server-https",
"ip": "10.10.10.10",
"port": "443",
"protocol": "https",
"readtimeout": 120,
"writetimeout": 120,
"headersize": 65536,
"log": {
"sys": "file:./logs/listener-https-sys.log",
}
}
]
```

3. "hosts" section

4. "engines" section
Expand Down Expand Up @@ -282,6 +345,14 @@ Extras:
Version Changes Control
=======================

v1.4.0 - 2020-08-12
-----------------------
- The context now have a Code attribute to pass the return code from an engine to the writer.
- The server now synchronize the returned code with the stat module so the correct returned code is logged.
- The engines can now return directly an error and the error will automatically be used to call error pages (available for library pages, wajafapp pages and any hand made extern engines).
- Engines has been adjusted to be able to return the error as an error (not a string).
- Manual enhanced (listeners config).

v1.3.7 - 2020-08-10
-----------------------
- Opened to TLS 1.3 (now support TLS 1.2 and TLS 1.3)
Expand Down
1 change: 1 addition & 0 deletions assets/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Context struct {
Request *http.Request // The request (and all its data available: headers, variables, form, files, etc)
Writer http.ResponseWriter // The request (and all its data available: headers, variables, form, files, etc)
IsMainPage bool // true it this page is the main page itself, false if any other page or blocks
Code int // return code
Language string // default system language by host. can be changed by code
Version string // default system version by host. can be changed by code
MainPage string // The original page URL called from outside
Expand Down
9 changes: 6 additions & 3 deletions engines/language/language.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package language

import (
"errors"
"net/http"
"time"

"github.com/webability-go/xcore/v2"
Expand Down Expand Up @@ -67,10 +69,11 @@ func (p *LanguageEngineInstance) Run(ctx *assets.Context, template *xcore.XTempl
// load the language data
data, err := xcore.NewXLanguageFromXMLFile(p.FilePath)
if err != nil {
ctx.LoggerError.Println("Error loading language:", err)
return nil
errortext := "Error loading language: " + p.FilePath + " " + err.Error()
ctx.Code = http.StatusInternalServerError
ctx.LoggerError.Println(errortext)
return errors.New(errortext)
}

LanguageCache.Set(p.FilePath, data)
return data
}
Expand Down
62 changes: 41 additions & 21 deletions engines/library/library.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package library

import (
"fmt"
"errors"
"net/http"
"os"
"os/exec"
"plugin"
Expand Down Expand Up @@ -75,7 +76,6 @@ func (p *LibraryEngineInstance) Run(ctx *assets.Context, template *xcore.XTempla
// verify if the code is compiled.
// BE CAREFULL OF MEMORY OVERLOAD FOR NEW VERSION HOT LOADED (hotload = any flag in config ? authorized/not authorized, # authorized, send alerts, monitor etc)
var lib *assets.Plugin
var err error

// If the plugin is not loaded, load it (equivalent of cache for other types of server)
// verify if the code is loaded in memory
Expand All @@ -97,10 +97,13 @@ func (p *LibraryEngineInstance) Run(ctx *assets.Context, template *xcore.XTempla
if !utils.FileExists(lib.SourcePath) {
if lib.Status != 2 {
lib.Status = 2
lib.Messages += "Error: " + lib.SourcePath + " Source file does not exists.\n"
errortext := "Error: " + lib.SourcePath + " Source file does not exists.\n"
ctx.LoggerError.Println(errortext)
lib.Messages += errortext
LibraryCache.Set(lib.SourcePath, lib)
}
return lib.Messages
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
}

mustcompile := true
Expand All @@ -117,48 +120,64 @@ func (p *LibraryEngineInstance) Run(ctx *assets.Context, template *xcore.XTempla
err := compiler.PleaseCompile(ctx, lib)
if err != nil {
lib.Status = 2
ctx.LoggerError.Println("ERROR: LIBRARY PAGE/BLOCK COULD NOT COMPILE", err)
lib.Messages += "Error: " + lib.SourcePath + " could not compile:\n" + fmt.Sprint(err)
errortext := "Error: the GO code could not compile " + lib.SourcePath + "\n" + err.Error()
ctx.LoggerError.Println(errortext)
lib.Messages += errortext
LibraryCache.Set(lib.SourcePath, lib)
return lib.Messages
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
}
}

if lib.Status == 0 { // needs to load the plugin
// Get GO BuildID to compare with in-memory GO BuildID and keep it with the library itself
// if already exists in memory, set it as default, or load it
buildid := getBuildId(lib.PluginVPath)
buildid, err := getBuildId(lib.PluginVPath)
if err != nil {
errortext := "Error: the library .so does not have a build id " + lib.SourcePath + "\n" + err.Error()
ctx.LoggerError.Println(errortext)
lib.Messages += errortext
LibraryCache.Set(lib.SourcePath, lib)
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
}
plg := lib.Libs[buildid]
if plg != nil { // already exists and loaded
lib.Lib = plg
} else {
lib.Lib, err = plugin.Open(lib.PluginVPath)
if err != nil {
lib.Status = 2
ctx.LoggerError.Println("ERROR: LIBRARY PAGE/BLOCK COULD NOT LOAD", err)
lib.Messages += "Error: " + lib.SourcePath + " could not load:\n" + fmt.Sprint(err)
errortext := "Error: the library .so could not load " + lib.SourcePath + "\n" + err.Error()
ctx.LoggerError.Println(errortext)
lib.Messages += errortext
LibraryCache.Set(lib.SourcePath, lib)
return lib.Messages
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
}
lib.Libs[buildid] = lib.Lib
}

fct, err := lib.Lib.Lookup("Run")
if err != nil {
lib.Status = 2
ctx.LoggerError.Println("ERROR: LIBRARY DOES NOT CONTAIN RUN FUNCTION", err)
lib.Messages += "Error: " + lib.SourcePath + " does not contain a Run function:\n" + fmt.Sprint(err)
errortext := "Error: the called library does not contain a Run function " + lib.SourcePath + "\n" + err.Error()
ctx.LoggerError.Println(errortext)
lib.Messages += errortext
LibraryCache.Set(lib.SourcePath, lib)
return lib.Messages
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
} else {
ok := false
lib.Run, ok = fct.(func(*assets.Context, *xcore.XTemplate, *xcore.XLanguage, interface{}) interface{})
if !ok {
lib.Status = 2
ctx.LoggerError.Println("ERROR: LIBRARY DOES NOT CONTAIN A VALID STANDARD RUN FUNCTION", err)
lib.Messages += "Error: " + lib.SourcePath + " does not contain a valid standard Run function:\n"
errortext := "Error: the called library does not contain a valid standard Run function " + lib.SourcePath + "\n" + err.Error()
ctx.LoggerError.Println(errortext)
lib.Messages += errortext
LibraryCache.Set(lib.SourcePath, lib)
return lib.Messages
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
} else {
lib.Status = 1
}
Expand All @@ -170,15 +189,16 @@ func (p *LibraryEngineInstance) Run(ctx *assets.Context, template *xcore.XTempla
return lib.Run(ctx, template, language, e)
}
// any error: return Messages
return lib.Messages
ctx.Code = http.StatusInternalServerError
return errors.New(lib.Messages)
}

func getBuildId(path string) string {
func getBuildId(path string) (string, error) {
cmd := exec.Command("go", "tool", "buildid", path)
out, err := cmd.CombinedOutput()
if err != nil {
// log error ?
return "Error running go tool buildid:\n" + fmt.Sprint(err)
return "", err
}
return string(out)
return string(out), nil
}
7 changes: 5 additions & 2 deletions engines/redirect/redirect.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package redirect

import (
"errors"
"net/http"

"github.com/webability-go/xamboo/assets"
Expand Down Expand Up @@ -32,6 +33,8 @@ func (re *RedirectEngine) Run(ctx *assets.Context, s interface{}) interface{} {
return ""
}
}
ctx.LoggerError.Println("Please specify redirecturl and redirectcode in .page")
return "Please specify redirecturl and redirectcode in .page"
errortext := "Please specify redirecturl and redirectcode in .page " + ctx.MainPage
ctx.Code = http.StatusInternalServerError
ctx.LoggerError.Println(errortext)
return errors.New(errortext)
}
7 changes: 6 additions & 1 deletion engines/simple/code.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package simple

import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -94,7 +96,10 @@ func (p *SimpleEngineInstance) Run(ctx *assets.Context, template *xcore.XTemplat
} else {
data, err := ioutil.ReadFile(p.FilePath)
if err != nil {
return "ERROR; .CODE FILE UNAVAILABLE " + p.FilePath
errortext := "Error; .code file unavailable " + p.FilePath
ctx.Code = http.StatusInternalServerError
ctx.LoggerError.Println(errortext)
return errors.New(errortext)
}
compiled = compileCode(string(data))
CodeCache.Set(p.FilePath, compiled)
Expand Down
Loading

0 comments on commit 8b83f2e

Please sign in to comment.