package server import ( "fmt" "io" "net/http" "os" "path" "reflect" "runtime/debug" "strings" "repositories.action2quare.com/ayo/gocommon/logger" ) const ( defaultMaxMemory = 32 << 10 // 32 KB ) type HoustonServerWithHandler interface { HoustonServer RegisterHandlers(serveMux *http.ServeMux, prefix string) error } type houstonHandler struct { HoustonServer methods map[string]reflect.Method } func NewHoustonHandler() HoustonServerWithHandler { var tmp *houstonHandler methods := make(map[string]reflect.Method) tp := reflect.TypeOf(tmp) for i := 0; i < tp.NumMethod(); i++ { method := tp.Method(i) methods[strings.ToLower(method.Name)] = method } return &houstonHandler{ HoustonServer: NewServer(), methods: methods, } } func (h *houstonHandler) RegisterHandlers(serveMux *http.ServeMux, prefix string) error { logger.Println("houstonHandler registed") serveMux.Handle("/"+path.Join(prefix, "houston"), h) fsx := http.FileServer(http.Dir("deploys")) serveMux.Handle(fmt.Sprintf("/%s/deploys/", prefix), http.StripPrefix(fmt.Sprintf("/%s/deploys/", prefix), fsx)) ufsx := http.FileServer(http.Dir("downloads")) serveMux.Handle(fmt.Sprintf("/%s/houston/downloads/", prefix), http.StripPrefix(fmt.Sprintf("/%s/houston/downloads/", prefix), ufsx)) serveMux.HandleFunc("/"+path.Join(prefix, "upload"), func(w http.ResponseWriter, r *http.Request) { defer func() { s := recover() if s != nil { logger.Println(s) debug.PrintStack() } io.Copy(io.Discard, r.Body) r.Body.Close() }() name := r.Header.Get("Houston-Service-Name") version := r.Header.Get("Houston-Service-Version") filename := r.Header.Get("Houston-Service-Filename") dir := fmt.Sprintf("downloads/%s/%s", name, version) if err := os.MkdirAll(dir, os.ModePerm); err == nil { file, _ := os.Create(path.Join(dir, filename)) if file != nil { defer file.Close() if _, err = io.Copy(file, r.Body); err != nil { w.WriteHeader(http.StatusInternalServerError) } } else { w.WriteHeader(http.StatusInternalServerError) } } else { w.WriteHeader(http.StatusInternalServerError) } }) return nil } func (h *houstonHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { defer func() { s := recover() if s != nil { logger.Println(s) debug.PrintStack() } }() defer func() { io.Copy(io.Discard, r.Body) r.Body.Close() }() var operation string if r.Method == "POST" { operation = r.FormValue("operation") } else { operation = r.URL.Query().Get("operation") } if len(operation) == 0 { w.WriteHeader(http.StatusBadRequest) return } method, ok := h.methods[strings.ToLower(operation)] if !ok { // 없는 operation logger.Println("fail to call api. operation is not valid :", operation) w.WriteHeader(http.StatusBadRequest) return } if r.PostForm == nil { r.ParseMultipartForm(defaultMaxMemory) } args := []reflect.Value{ reflect.ValueOf(h), reflect.ValueOf(w), reflect.ValueOf(r), } method.Func.Call(args) }