An Express JS Style HTTP server implementation in Golang with safe cleanup exit. The package make use of similar framework convention as there are in express-js. People switching from NodeJS to Golang often end up in a bad learning curve to start building their webapps, this project is meant to ease things up, its a light weight framework which can be extended to do any number of functionality.
package main
import (
express "github.com/DronRathore/goexpress"
)
func main (){
var app = express.Express()
app.Get("/", func(req express.Request, res express.Response){
res.Write("Hello World")
// you can skip closing connection
})
app.Start("8080")
}
The router works in the similar way as it does in the express-js. You can have named parameters in the URL or named + regex combo.
func main (){
var app = express.Express()
app.Get("/:service/:object([0-9]+)", func(req express.Request, res express.Response){
res.JSON(req.Params().Get("service"))
})
app.Start("8080")
}
Note: You can also adhoc an express.Router() instance too much like it is done in expressjs
package main
import (
express "github.com/DronRathore/goexpress"
)
var LibRoutes = func (){
// create a new Router instance which works in similar way as app.Get/Post etc
var LibRouter = express.NewRouter()
LibRouter.Get("/lib/:api_version", func(req express.Request, res express.Response){
res.Json(req.Params.Get("api_version"))
})
return *LibRoutes
}() // immediate invocation
func main(){
var app = express.Express()
app.Use(LibRoutes) // attaches the Library Routes
app.Start("8080")
}
You can write custom middlewares, wrappers in the similar fashion. Middlewares can be used to add websocket upgradation lib, session handling lib, static assets server handler
func main (){
var app = express.Express()
app.Use(func(req *express.Request, res *express.Response){
req.Params.Set("I-Am-Adding-Something", "something")
})
app.Get("/:service/:object([0-9]+)", func(req express.Request, res express.Response){
// json will have the key added
res.JSON(req.Params.Get("service"))
})
app.Start("8080")
}
You can pass around the instance of express struct across packages using this interface.
func main(){
var app = express.Express()
attachHandlers(app)
}
func attachHandlers(instance express.ExpressInterface){
instance.Use(someMiddleware)
instance.Set("logging", true)
}
import (
express "github.com/DronRathore/goexpress"
http "net/http"
Time "time"
)
func main (){
var app = express.Express()
app.Use(func(req express.Request, res express.Response){
var cookie = &http.Cookie{
Name: "name",
Value: "value",
Expires: Time.Unix(0, 0)
}
res.Cookie.Add(cookie)
req.Params.Set("session_id", req.Cookies.Get("session_id"))
})
app.Get("/", func(req express.Request, res express.Response){
res.Write("Hello World")
})
app.Start("8080")
}
You can send a file by using the helper res.SendFile(url string, doNotSendCachedData bool)
func main (){
var app = express.Express()
app.Get("/public/:filename", func(req express.Request, res express.Response){
res.SendFile(filename, false)
})
app.Start("8080")
}
Note: You can now also send an auto downloadable file too using res.Download api
/*
@params:
path: Full path to the file in local machine
filename: The name to be sent to the client
*/
res.Download(path string, filename string)
func main (){
var app = express.Express()
app.Use(func(req *express.Request, res *express.Response){
res.Params.Set("I-Am-Adding-Something", "something")
})
app.Post("/user/new", func(req express.Request, res express.Response){
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
var list = &User{Name: req.Body("name")[0], Email: req.Body("email")[0]}
res.JSON(list)
})
app.Start("8080")
}
JSON Post data manipulation in golang is slightly different from JS. You have to pass a filler to the decoder, the decoder assumes the data to be in the same format as the filler, if it is not, it throws an error.
func main (){
var app = express.Express()
app.Use(func(req express.Request, res express.Response){
res.Params["I-Am-Adding-Something"] = "something"
})
app.Post("/user/new", func(req express.Request, res express.Response){
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
var list User
err := req.JSON().Decode(&list)
if err != nil {
res.Error(400, "Invalid JSON")
} else {
res.JSON(list)
}
})
app.Start("8080")
}
If a request has content-type form-data with a valid bounday param than goexpress will automatically parse and load all the files in express.Files() array. It will also populate req.Body() if the post/put request contains any text key values.
func(req *express.Request, res *express.Response){
if len(req.Files) > 0 {
// do something
for _, file := range req.Files() {
name := file.FormName
type := file.Mime["Content-Type"]
res.Header().Set("Content-Type", type)
content, err := ioutil.ReadAll(file.File)
// save content or throw error
}
}
}
Use standard Golang http templates to render response page.
For example, you have a template file index.html in templates directory:
<h1>{{.Name}}</h1>
Fill the context and provide a path to the template file:
func(req *express.Request, res *express.Response){
type TmplContext struct{
Name string
}
data := TmplContext{"Rob"}
res.Render("template.html", &data)
}
Newer version of goexpress provides three new methods namely express.ShutdownTimeout, express.BeforeShutdown and express.Shutdown, these methods can be utilised to do cleanup before the server shuts down.
time.Duration to spend while shutting down the serverThere are no testing added to this package yet, I am hoping to get my hands dirty in testing, if anyone can help me out with this, feel free to open a PR.
$ claude mcp add goexpress \
-- python -m otcore.mcp_server <graph>