mirror of
https://github.com/semaphoreui/semaphore.git
synced 2025-01-20 15:29:28 +01:00
Merge pull request #632 from ansible-semaphore/fix-api-trailing-slash
fix(api): remove redirect for calls without trailing slash
This commit is contained in:
commit
eee34fb266
@ -51,7 +51,7 @@ func notFoundHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Route declares all routes
|
||||
func Route() *mux.Router {
|
||||
r := mux.NewRouter().StrictSlash(true)
|
||||
r := mux.NewRouter()
|
||||
r.NotFoundHandler = http.HandlerFunc(servePublic)
|
||||
|
||||
webPath := "/"
|
||||
@ -90,9 +90,9 @@ func Route() *mux.Router {
|
||||
authenticatedAPI.Path("/users").HandlerFunc(getUsers).Methods("GET", "HEAD")
|
||||
authenticatedAPI.Path("/users").HandlerFunc(addUser).Methods("POST")
|
||||
|
||||
tokenAPI := authenticatedAPI.PathPrefix("/user").Subrouter()
|
||||
authenticatedAPI.Path("/user").HandlerFunc(getUser).Methods("GET", "HEAD")
|
||||
|
||||
tokenAPI.Path("/").HandlerFunc(getUser).Methods("GET", "HEAD")
|
||||
tokenAPI := authenticatedAPI.PathPrefix("/user").Subrouter()
|
||||
tokenAPI.Path("/tokens").HandlerFunc(getAPITokens).Methods("GET", "HEAD")
|
||||
tokenAPI.Path("/tokens").HandlerFunc(createAPIToken).Methods("POST")
|
||||
tokenAPI.HandleFunc("/tokens/{token_id}", expireAPIToken).Methods("DELETE")
|
||||
@ -100,15 +100,21 @@ func Route() *mux.Router {
|
||||
userAPI := authenticatedAPI.PathPrefix("/users/{user_id}").Subrouter()
|
||||
userAPI.Use(getUserMiddleware)
|
||||
|
||||
userAPI.Path("/").HandlerFunc(getUser).Methods("GET", "HEAD")
|
||||
userAPI.Path("/").HandlerFunc(updateUser).Methods("PUT")
|
||||
userAPI.Path("/").HandlerFunc(deleteUser).Methods("DELETE")
|
||||
userAPI.Path("/password").HandlerFunc(updateUserPassword).Methods("POST")
|
||||
userAPI.Methods("GET", "HEAD").HandlerFunc(getUser)
|
||||
userAPI.Methods("PUT").HandlerFunc(updateUser)
|
||||
userAPI.Methods("DELETE").HandlerFunc(deleteUser)
|
||||
|
||||
userPasswordAPI := authenticatedAPI.PathPrefix("/users/{user_id}").Subrouter()
|
||||
userPasswordAPI.Use(getUserMiddleware)
|
||||
userPasswordAPI.Path("/password").HandlerFunc(updateUserPassword).Methods("POST")
|
||||
|
||||
projectGet := authenticatedAPI.Path("/project/{project_id}").Subrouter()
|
||||
projectGet.Use(projects.ProjectMiddleware)
|
||||
projectGet.Methods("GET", "HEAD").HandlerFunc(projects.GetProject)
|
||||
|
||||
projectUserAPI := authenticatedAPI.PathPrefix("/project/{project_id}").Subrouter()
|
||||
projectUserAPI.Use(projects.ProjectMiddleware)
|
||||
|
||||
projectUserAPI.Path("/").HandlerFunc(projects.GetProject).Methods("GET", "HEAD")
|
||||
projectUserAPI.Path("/events").HandlerFunc(getAllEvents).Methods("GET", "HEAD")
|
||||
projectUserAPI.HandleFunc("/events/last", getLastEvents).Methods("GET", "HEAD")
|
||||
|
||||
@ -136,9 +142,12 @@ func Route() *mux.Router {
|
||||
projectAdminAPI := authenticatedAPI.PathPrefix("/project/{project_id}").Subrouter()
|
||||
projectAdminAPI.Use(projects.ProjectMiddleware, projects.MustBeAdmin)
|
||||
|
||||
projectAdminAPI.Path("/").HandlerFunc(projects.UpdateProject).Methods("PUT")
|
||||
projectAdminAPI.Path("/").HandlerFunc(projects.DeleteProject).Methods("DELETE")
|
||||
projectAdminAPI.Path("/users").HandlerFunc(projects.AddUser).Methods("POST")
|
||||
projectAdminAPI.Methods("PUT").HandlerFunc(projects.UpdateProject)
|
||||
projectAdminAPI.Methods("DELETE").HandlerFunc(projects.DeleteProject)
|
||||
|
||||
projectAdminUsersAPI := authenticatedAPI.PathPrefix("/project/{project_id}").Subrouter()
|
||||
projectAdminUsersAPI.Use(projects.ProjectMiddleware, projects.MustBeAdmin)
|
||||
projectAdminUsersAPI.Path("/users").HandlerFunc(projects.AddUser).Methods("POST")
|
||||
|
||||
projectUserManagement := projectAdminAPI.PathPrefix("/users").Subrouter()
|
||||
projectUserManagement.Use(projects.UserMiddleware)
|
||||
@ -232,31 +241,33 @@ func debugPrintRoutes(r *mux.Router) {
|
||||
|
||||
//nolint: gocyclo
|
||||
func servePublic(w http.ResponseWriter, r *http.Request) {
|
||||
path := r.URL.Path
|
||||
|
||||
htmlPrefix := ""
|
||||
if util.Config.OldFrontend {
|
||||
htmlPrefix = "/html"
|
||||
}
|
||||
|
||||
publicAssetsPrefix := ""
|
||||
if util.Config.OldFrontend {
|
||||
publicAssetsPrefix = "public"
|
||||
}
|
||||
|
||||
webPath := "/"
|
||||
if util.WebHostURL != nil {
|
||||
webPath = util.WebHostURL.RequestURI()
|
||||
}
|
||||
|
||||
path := r.URL.Path
|
||||
|
||||
if path == webPath + "api" || strings.HasPrefix(path, webPath + "api/") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
htmlPrefix := ""
|
||||
publicAssetsPrefix := ""
|
||||
if util.Config.OldFrontend {
|
||||
htmlPrefix = "/html"
|
||||
publicAssetsPrefix = "public"
|
||||
}
|
||||
|
||||
if publicAssetsPrefix != "" && !strings.HasPrefix(path, webPath+publicAssetsPrefix) {
|
||||
if len(strings.Split(path, ".")) > 1 {
|
||||
if strings.Contains(path, ".") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
path = htmlPrefix+"/index.html"
|
||||
} else if len(strings.Split(path, ".")) == 1 {
|
||||
} else if !strings.Contains(path, ".") {
|
||||
path = htmlPrefix+"/index.html"
|
||||
}
|
||||
|
||||
|
11
cli/main.go
11
cli/main.go
@ -21,6 +21,15 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
)
|
||||
|
||||
func cropTrailingSlashMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
r.URL.Path = strings.TrimSuffix(r.URL.Path, "/")
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
util.ConfigInit()
|
||||
if util.InteractiveSetup {
|
||||
@ -69,7 +78,7 @@ func main() {
|
||||
|
||||
fmt.Println("Server is running")
|
||||
|
||||
err := http.ListenAndServe(util.Config.Interface+util.Config.Port, nil)
|
||||
err := http.ListenAndServe(util.Config.Interface+util.Config.Port, cropTrailingSlashMiddleware(router))
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
@ -734,7 +734,7 @@ export default {
|
||||
}
|
||||
this.user = (await axios({
|
||||
method: 'get',
|
||||
url: '/api/user/',
|
||||
url: '/api/user',
|
||||
responseType: 'json',
|
||||
})).data;
|
||||
},
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
<v-text-field
|
||||
v-model="item.name"
|
||||
label="Playbook Alias"
|
||||
label="Project Name"
|
||||
:rules="[v => !!v || 'Project name is required']"
|
||||
required
|
||||
:disabled="formSaving"
|
||||
|
@ -15,6 +15,7 @@ export default class Socket extends Listenable {
|
||||
if (!this.isRunning()) {
|
||||
return;
|
||||
}
|
||||
this.ws = null;
|
||||
setTimeout(() => {
|
||||
this.start();
|
||||
}, 2000);
|
||||
|
Loading…
Reference in New Issue
Block a user