path_processor.go 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package restful
  2. import (
  3. "bytes"
  4. "strings"
  5. )
  6. // Copyright 2018 Ernest Micklei. All rights reserved.
  7. // Use of this source code is governed by a license
  8. // that can be found in the LICENSE file.
  9. // PathProcessor is extra behaviour that a Router can provide to extract path parameters from the path.
  10. // If a Router does not implement this interface then the default behaviour will be used.
  11. type PathProcessor interface {
  12. // ExtractParameters gets the path parameters defined in the route and webService from the urlPath
  13. ExtractParameters(route *Route, webService *WebService, urlPath string) map[string]string
  14. }
  15. type defaultPathProcessor struct{}
  16. // Extract the parameters from the request url path
  17. func (d defaultPathProcessor) ExtractParameters(r *Route, _ *WebService, urlPath string) map[string]string {
  18. urlParts := tokenizePath(urlPath)
  19. pathParameters := map[string]string{}
  20. for i, key := range r.pathParts {
  21. var value string
  22. if i >= len(urlParts) {
  23. value = ""
  24. } else {
  25. value = urlParts[i]
  26. }
  27. if r.hasCustomVerb && hasCustomVerb(key) {
  28. key = removeCustomVerb(key)
  29. value = removeCustomVerb(value)
  30. }
  31. if strings.Index(key, "{") > -1 { // path-parameter
  32. if colon := strings.Index(key, ":"); colon != -1 {
  33. // extract by regex
  34. regPart := key[colon+1 : len(key)-1]
  35. keyPart := key[1:colon]
  36. if regPart == "*" {
  37. pathParameters[keyPart] = untokenizePath(i, urlParts)
  38. break
  39. } else {
  40. pathParameters[keyPart] = value
  41. }
  42. } else {
  43. // without enclosing {}
  44. startIndex := strings.Index(key, "{")
  45. endKeyIndex := strings.Index(key, "}")
  46. suffixLength := len(key) - endKeyIndex - 1
  47. endValueIndex := len(value) - suffixLength
  48. pathParameters[key[startIndex+1:endKeyIndex]] = value[startIndex:endValueIndex]
  49. }
  50. }
  51. }
  52. return pathParameters
  53. }
  54. // Untokenize back into an URL path using the slash separator
  55. func untokenizePath(offset int, parts []string) string {
  56. var buffer bytes.Buffer
  57. for p := offset; p < len(parts); p++ {
  58. buffer.WriteString(parts[p])
  59. // do not end
  60. if p < len(parts)-1 {
  61. buffer.WriteString("/")
  62. }
  63. }
  64. return buffer.String()
  65. }