Golang Microservices Framework GO-Zero series 4: Go-Zero file services

Go-zero itself supports file services, but we need to write the relevant handler files, which is the purpose of this article

  • Do not write any handlers related to files
  • If you have a new file, just put the file template in a specific directory without touching any go code

The demand is here. Let’s do it

You may need to read the code before you start

Golang Micro-service framework GO-Zero series-1: Using XormV2 in Go-Zero Golang micro-service framework GO-Zero series-2: Using JWT-Token in Go-Zero Authentication practice Golang Microservices framework GO-Zero series-3: Extends Go-Zero to support HTML template parsing automation

Pay attention to

Micro services require resource separation. In actual production, professional file servers or third-party storage platforms such as OSS should be used

File service implementation idea

There is a dedicated static file service package in GIN that Go-Zero does not currently provide. Currently Go-Zero provides very strict path matching, such that accessing /asset/ L1.jpg will map to handlerlv1 /asset/ L1 /l2.jpg will map to handlerlv2 for /asset/:1/:2 There are two situations

Maps a specified path to a single file

/ WWW /favourite. Ico file

// Pass in the file address
func filehandler(filepath string) http.HandlerFunc {
	return func(w http.ResponseWriter, req *http.Request) {
		http.ServeFile(w, req, filepath)
	}
}
Copy the code

Call the AddRoute method to add a single route to the router

func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {

// Add a single
engine.AddRoute(
				rest.Route{
					Method:  http.MethodGet,
					Path:    "/favourite.ico",
					Handler: filehandler("./www/favourite.ico"),})}Copy the code

Map the specified directory and provide services

In the actual process, we need to expose a certain directory, such as /assets/, which stores some resource files such as CSS, JS,img, etc

tree /f +---assets | +---css | +---fonts | +---images | +---js | \---plugins | +---font-awesome | | +---css | | \---fonts | +---fontawesome | | +---css | | \---fonts | +---ionicons | | +---css | | \---fonts | +---jquery.contextmenu | | \ | + -- -- -- -- -- -- images jquery. Pin | | + -- -- -- the CSS | | \ | + -- -- -- -- -- -- images jqueryui - 1.12.1 | | + -- -- -- external | | | \ - jquery | | | \ \ -- -- -- images swiper - 4.5.3 | | + -- -- -- CSS \ - jsCopy the code

If you use a single file to implement this, it is definitely not reasonable because the router is very large. How to solve this problem? We can implement the folder service using the following method

//
func dirhandler(patern, filedir string) http.HandlerFunc {

	return func(w http.ResponseWriter, req *http.Request) {
		handler := http.StripPrefix(patern, http.FileServer(http.Dir(filedir)))
		handler.ServeHTTP(w, req)

	}
}
Copy the code

The core function is http.stripprefix (patern, http.fileserver (http.dir (filedir))), which maps the patern format to a directory filedir

  • Patern: Request path format/assets/:1./assets/:1/:2This kind of
  • Filedir: mapping the corresponding folder./assets/This kind of

All we need to do is build a mapping between the multi-level file access format and dirHandler

func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {

			// Register here
			dirlevel := []string{": 1.".": 2".": 3".: "4"."5".: "6".": 7".", 8"}
			patern := "/asset/"
			dirpath := "./assets/"
			for i := 1; i < len(dirlevel); i++ {
				path := prefix + strings.Join(dirlevel[:i], "/")
				// Finally generate /asset
				engine.AddRoute(
					rest.Route{
						Method:  http.MethodGet,
						Path:    path,
						Handler: dirhandler(patern,dirpath),
					})

				logx.Infof("register dir %s %s", path,dirpath)
			}
}
Copy the code

404

404 can be configured in the main function

rt := router.NewPatRouter()
	rt.SetNotFoundHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		// The content here can be customized
		w.Write([]byte("The server is distracted. It's customizable."))
	}))
	server := rest.MustNewServer(c.RestConf, rest.WithRouter(rt))
Copy the code

Request at this time, http://127.0.0.1:8888/hello, system response server somewhere, it can be customized

test

Start the system

E:\workspace@go\gozero\file>go run file.go
2020/09/05 20:18:24 {"@timestamp":"Did all the T20:2020-09-05. 682 + 08"."level":"info"."content":"{{{file-api {console logs info false 0 100} pro {0}} 0.0.0.0 8081 false 10000 1048576 3000 900 {false 0s []}} [/asset/=./assets]}"} 
{"@timestamp":"Did all the T20:2020-09-05. 682 + 08"."level":"info"."content":"register dir /asset/:1 ./assets"}
{"@timestamp":"Did all the T20:2020-09-05. 683 + 08"."level":"info"."content":"register dir /asset/:1/:2 ./assets"}
{"@timestamp":"Did all the T20:2020-09-05. 683 + 08"."level":"info"."content":"register dir /asset/:1/:2/:3 ./assets"}
{"@timestamp":"Did all the T20:2020-09-05. 683 + 08"."level":"info"."content":"register dir /asset/:1/:2/:3/:4 ./assets"}
{"@timestamp":"Did all the T20:2020-09-05. 697 + 08"."level":"info"."content":"register dir /asset/:1/:2/:3/:4/:5 ./assets"}
{"@timestamp":"Did all the T20:2020-09-05. 697 + 08"."level":"info"."content":"register dir /asset/:1/:2/:3/:4/:5/:6 ./assets"}
{"@timestamp":"Did all the T20:2020-09-05. 698 + 08"."level":"info"."content":"register dir /asset/:1/:2/:3/:4/:5/:6/:7 ./assets"}

Copy the code

The access system responds normally

http://127.0.0.1:8888/asset/images/avatar.jpg http://127.0.0.1:8888/asset/js/test.js http://127.0.0.1:8888/asset/js/lv2/test.js

Note that /asset/** is requested, not /assets/**

Think about it

We can implement file services based on req.url.path in NotFoundHandler. How?

The next chapter forecast

The basic sorting of individual application needs will be completed and the micro-service will start tomorrow

Code acquisition for this article

Gozero integration jWT-token (goZero integration jWT-token (goZero integration jWT-token) Betaidea input goZero to goZero entry code

Spread the word

Send benefits to uniAPP users Gospel is coming! After hundreds of thousands of users, our customer service system is finally available. Are you still worried about mall access to customer service? Just one line of code to access!! Just one line of code!!!!

/*kefu.vue*/
<template>
	<view>
		<IdeaKefu :siteid="siteId"  ></IdeaKefu>
	</view>
</template>

<script>
	import IdeaKefu from "@/components/idea-kefu/idea-kefu.vue"
    export default {
		components:{
			IdeaKefu
		},
		data() {
			return {
				siteId:2}}}Copy the code

The effect is great

Address kefu.techidea8.com/html/wiki/ development document