README
Table of Content
- Table of Content
- Tool Story
- Big Picture, as I said
- How to use
- API
- Build and Test
- Code of Conduct
- Contributor
Tool Story
This is project BaiQi of DeepDigEst Inc., which maybe ⏰ simplify the backend app development workflow.
Our server guys have made lots of discussions about to which logic-glue framework we should adopt and decided to choose node.js, the flighty yet powerful VM.
Since then, we have talked about which language system we should fit into, it's all about easy maintenance and quick training for the new stuff, the plain js, traceurjs, babeljs and so on. Finally, we made a united agree on that it must be typescript - microsoft's typed javascript. Yes, microsoft is great again cause she said she loves oss and linux? 😊
This server framework is aimed at the goal - "simple, fast, debug-faced and stable". It's used for holding the big application logic layer of our backend system. For now we have done a few awesome features like tasks switching, debug information recording and request-response object initializing.
In the future, we will give our best to get continual improvements. Maybe there should be some thing like Roadmap or big picture? 😢 I hate to write doc, you know, my boss would never pay for the doc working, which is the most terrible thing, IMO.
Good luck for this project!
Big Picture, as I said
The HTTP Request - by our simple view point - is consist of below parts:
- HTTP method: GET, PUT, POST or DELETE.
- HTTP path: /api/v1/hello?foo=bar&a=b
- HTTP payload: the body of http request.
The whole of system is intrinsically a pre-config system, and all we need to do is just writing the right configure file according to the app logic. But, you should use the code as config principal instead of using the normal json configuration.
In terminology, we call that step - making the Task Process Tree(TPT)
, and every node or leaf of that tree becomes the Router Node
.
We define that every time when you meet a /
symbol in the path string, the layers of TPT should increase one. This is the most important convention we should use.
A single router node has three important properties:
- the matching path - used to matching http path, and
- the matching method - used to matching http method.
- the tasks - used to processing the matched http request, could be a single task or a chain of tasks.
We think, for app logic developers, the first two parts shall fully qualify a http request and the third part is about how to explain our logic code.
The tasks can make different process in terms of the Request
object passed into, or call the next()
function to pass the control to next matching tasks, exactly as the express
framework.🤡
For brevity, whole system consists of routers, and single router consists of matching path, method and tasks.
The most important claim, do not resort the skip-level mounting, in which you mount the non direct descendant. Think like this:
// Do not use this!
router.dde_mount("/api/v1, router_v1");
For specific http request, system will give us an integrated TPT. And this TPT will be the key for future performance monitor, optimization and task testing.
How to use
Use npm
to install @sevenryze/server
, then import the only exported class.
import { Router } from "@sevenryze/server"
// Or commonjs
const { Router } = require("@sevenryze/server");
let router = new Router();
API
serveStatic
The static files serve utility shameless borrowed from node module serve-static
.
See more info: https://github.com/expressjs/serve-static
Router()
Router
class, used for initializing the router object.
let router = new Router();
// You can now use router to compose the whole system.
dde_mount(path, router)
path
: the path mounted by sub-router.router
: the sub-router.
Mount different Router
hierarchically to compose the whole response chain.
router_root.dde_mount("/v1", router_v1);
router_v1.dde_mount("/user", router_user);
dde_METHOD(task)
task: (request, response, next) => void
: The task function will get three parameters -request
,response
,next
, corresponding the Request, Respond of http request and the control passing functionnext()
respectively.
Register the task processing function into router. We support a few common http method
:
GET
request -dde_get()
.POST
request -dde_post()
.PUT
request -dde_put()
.DELETE
request -dde_delete()
.- Match all methods on the same router -
dde_all
. - Match all methods on the same and descendant routers -
dde_common()
.
Note: Generally, on every place where you need to call the next()
to pass the control, you should use the form return next();
to eliminate the side-effect.
Want to know why? see my blog, if there are... 🤡
// sync task
router.dde_get( (request, response, next) => {
// Do something.
response.dde_send();
return next();
});
// async task
router.dde_get(async (request, response, next) => {
// Do something.
return next();
})
Request
Helpers on
: string request.dde_originalUrl
Original, unprocessed request url.
: Url request.dde_parsedUrl
The parsed http url, see https://nodejs.org/dist/latest-v9.x/docs/api/url.html#url_url_strings_and_url_objects for more info.
: object request.dde_queryString
The query string key-value pairs parsed into object format.
: Respond request.dde_response
Point to the accompanied Response object.
: string request.dde_method
The request http method.
: object request.dde_headers
The http headers parsed into object format.
: Task[] request.dde_taskList
The tasks waiting for this request.
: any request.tmp\_\*
The app context variable for simply share state between tasks. Must be the tmp** format.
: () => string request.dde_getIp()
Get the client ip and be able to handle behind proxy case.
request.dde_getIp();
// => "127.0.0.1"
Response
Helpers on
: Request response.dde_request
Points to the accompanied request object.
: (object) => Respond response.dde_setHeader(object)
- object
- Object used to set the headers, such as { Accept: "text/plain", "X-API-Key": "dde" }.
Set header key
to its value
. If the Content-Type
field is going to be set, this method will automatically turn the value to extensional form, eg."html" to the standard mime forms "text/html", and add the charset if it can be matched in mime-db package.
Return the this object, aka. Respond to make chain-able calls available.
response.dde_setHeader({ Accept: "text/plain", "X-API-Key": "xmt" });
// => Accept: "text/plain"
// => X-API-Key: "xmt"
response.dde_setHeader({ "Content-Type": "json" });
// => Content-Type: "application/json; charset=utf-8"
response.dde_setHeader({ "Content-Type": "html" });
// => Content-Type: "text/html; charset=utf-8"
response.dde_setHeader({ "Content-Type": "bin" });
// => Content-Type: "application/octet-stream"
: (code: number) => Response response.dde_setStatus(code)
- code
- Http status code number such as "404"
Set the status code
of the response.
Return this object for chain-able calls.
response.dde_setStatus(404);
: (body?) => Response response.dde_send(body)
- body <string | object | buffer> - Can be a string such as
"some string"
, an object such as{some: "haha"}
and a buffer such asnew Buffer("some buffer")
.
Send response to the remote client, and this method will terminate the underlying socket session.
response.dde_send(new Buffer("some buffer"));
response.dde_send({ some: "json" });
response.dde_send("<p>some html</p>");
dde_listen(port)
- port: The port listening to.
Listen the specific port.
router.dde_listen(7777);
dde_close()
Close the server.
router.dde_close();
Build and Test
Build
Use typescript to compile. For more information, you should check the tsconfig.ts file.
npm run build
Test
We use a well-known combination test set - jest
by facebook. You are to use npm test script to test all, like:
npm run test
And if you need to generate test coverage, use:
npm run test-coverage
Code of Conduct
- You are not rambo. Remember that together we are a team.
- Please invite someone to review your code, again, you are not immortal.
- Never blame other workmate for the quality of code set, you should know that boss already fined the poor guy.
Contributor
- Seven Ryze - XmT Inc.
- Cris - XmT Inc.
- Becky - XmT Inc.
Rangeragent - XmT Inc.