mirror of
https://github.com/bytedream/docker4ssh.git
synced 2025-06-27 01:40:32 +02:00
Initial commit
This commit is contained in:
123
server/api/api.go
Normal file
123
server/api/api.go
Normal file
@ -0,0 +1,123 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"docker4ssh/config"
|
||||
"docker4ssh/ssh"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type EndpointHandler struct {
|
||||
http.Handler
|
||||
|
||||
auth bool
|
||||
|
||||
get func(http.ResponseWriter, *http.Request, *ssh.User) (interface{}, int)
|
||||
post func(http.ResponseWriter, *http.Request, *ssh.User) (interface{}, int)
|
||||
}
|
||||
|
||||
func (h *EndpointHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ip := strings.Split(r.RemoteAddr, ":")[0]
|
||||
|
||||
zap.S().Infof("User connected to api with remote address %s", ip)
|
||||
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
|
||||
user := ssh.GetUser(ip)
|
||||
// checks if auth should be checked and if so and no user could be found, response an error
|
||||
if h.auth && user == nil {
|
||||
zap.S().Errorf("Could not find api user with ip %s", ip)
|
||||
json.NewEncoder(w).Encode(APIError{Message: "unauthorized"})
|
||||
return
|
||||
} else if user != nil {
|
||||
zap.S().Debugf("API ip %s is %s", ip, user.ID)
|
||||
}
|
||||
|
||||
raw := bytes.Buffer{}
|
||||
if r.ContentLength > 0 {
|
||||
io.Copy(&raw, r.Body)
|
||||
defer r.Body.Close()
|
||||
if !json.Valid(raw.Bytes()) {
|
||||
zap.S().Errorf("API user %s sent invalid body", ip)
|
||||
w.WriteHeader(http.StatusNotAcceptable)
|
||||
json.NewEncoder(w).Encode(APIError{Message: "invalid body"})
|
||||
return
|
||||
}
|
||||
r.Body = ioutil.NopCloser(&raw)
|
||||
}
|
||||
|
||||
zap.S().Debugf("API user %s request - \"%s %s %s\" \"%s\" \"%s\"", ip, r.Method, r.URL.Path, r.Proto, r.UserAgent(), raw.String())
|
||||
|
||||
var response interface{}
|
||||
var code int
|
||||
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
if h.get != nil {
|
||||
response, code = h.get(w, r, user)
|
||||
}
|
||||
case http.MethodPost:
|
||||
if h.post != nil {
|
||||
response, code = h.post(w, r, user)
|
||||
}
|
||||
}
|
||||
|
||||
if response == nil && code == 0 {
|
||||
zap.S().Infof("API user %s sent invalid method: %s", ip, r.Method)
|
||||
response = APIError{Message: fmt.Sprintf("invalid method '%s'", r.Method)}
|
||||
code = http.StatusConflict
|
||||
} else {
|
||||
zap.S().Infof("API user %s issued %s successfully", ip, r.URL.Path)
|
||||
}
|
||||
|
||||
w.WriteHeader(code)
|
||||
if response != nil {
|
||||
json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
}
|
||||
|
||||
func ServeAPI(config *config.Config) (errChan chan error, closer func() error) {
|
||||
errChan = make(chan error, 1)
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
mux.Handle("/ping", &EndpointHandler{
|
||||
get: PingGet,
|
||||
})
|
||||
mux.Handle("/error", &EndpointHandler{
|
||||
get: ErrorGet,
|
||||
})
|
||||
mux.Handle("/info", &EndpointHandler{
|
||||
get: InfoGet,
|
||||
auth: true,
|
||||
})
|
||||
mux.Handle("/config", &EndpointHandler{
|
||||
get: ConfigGet,
|
||||
post: ConfigPost,
|
||||
auth: true,
|
||||
})
|
||||
mux.Handle("/auth", &EndpointHandler{
|
||||
get: AuthGet,
|
||||
post: AuthPost,
|
||||
auth: true,
|
||||
})
|
||||
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", config.Api.Port))
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
errChan <- http.Serve(listener, mux)
|
||||
}()
|
||||
|
||||
return errChan, listener.Close
|
||||
}
|
Reference in New Issue
Block a user