1
0

tokenize.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package nginx
  2. import (
  3. "bufio"
  4. "regexp"
  5. "strings"
  6. "unicode"
  7. )
  8. func (c *NgxConfig) parseServer(scanner *bufio.Scanner) {
  9. server := NewNgxServer()
  10. server.Directives = make(NgxDirectives)
  11. for scanner.Scan() {
  12. d := parseDirective(scanner)
  13. switch d.Directive {
  14. case Location:
  15. server.parseLocation(d.Params)
  16. case CommentStart:
  17. server.commentQueue.Enqueue(d.Params)
  18. default:
  19. server.parseDirective(d)
  20. }
  21. }
  22. // attach comments which are over the current server
  23. server.Comments = c.commentQueue.DequeueAllComments()
  24. c.Servers = append(c.Servers, *server)
  25. }
  26. func (c *NgxConfig) parseUpstream(scanner *bufio.Scanner) {
  27. upstream := NgxUpstream{}
  28. upstream.Directives = make(NgxDirectives)
  29. d := NgxDirective{}
  30. for scanner.Scan() {
  31. text := strings.TrimSpace(scanner.Text())
  32. // escape empty line or comment line
  33. if len(text) < 1 || text[0] == '#' {
  34. return
  35. }
  36. sep := len(text) - 1
  37. for k, v := range text {
  38. if unicode.IsSpace(v) {
  39. sep = k
  40. break
  41. }
  42. }
  43. d.Directive = text[0:sep]
  44. d.Params = strings.Trim(text[sep:], ";")
  45. if d.Directive == Server {
  46. upstream.Directives[d.Directive] = append(upstream.Directives[d.Directive], d)
  47. } else if upstream.Name == "" {
  48. upstream.Name = d.Directive
  49. }
  50. }
  51. // attach comments which are over the current upstream
  52. upstream.Comments = c.commentQueue.DequeueAllComments()
  53. c.Upstreams = append(c.Upstreams, upstream)
  54. }
  55. func (s *NgxServer) parseDirective(d NgxDirective) {
  56. orig := d.Orig()
  57. // handle inline comments
  58. str, comments, _ := strings.Cut(orig, "#")
  59. regExp := regexp.MustCompile("(\\S+?)\\s+{?(.+?)[;|}]")
  60. matchSlice := regExp.FindAllStringSubmatch(str, -1)
  61. for k, v := range matchSlice {
  62. // [[gzip_min_length 256; gzip_min_length 256] [gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth] [gzip on; gzip on] [gzip_vary on; gzip_vary on] [location /x/ {} location /x/ {] [gzip_comp_level 4; gzip_comp_level 4]]
  63. if len(v) > 0 {
  64. scanner := bufio.NewScanner(strings.NewReader(v[0]))
  65. if scanner.Scan() {
  66. d = parseDirective(scanner)
  67. // inline location
  68. if d.Directive == Location {
  69. s.parseLocation(d.Orig())
  70. } else {
  71. if k == 0 {
  72. d.Comments = s.commentQueue.DequeueAllComments()
  73. } else if k == len(matchSlice)-1 {
  74. d.Comments = comments
  75. }
  76. // trim right ';'
  77. d.TrimParams()
  78. // map[directive]=>[]Params
  79. s.Directives[d.Directive] = append(s.Directives[d.Directive], d)
  80. }
  81. }
  82. }
  83. }
  84. }
  85. func (s *NgxServer) parseLocation(str string) {
  86. path, content, _ := strings.Cut(str, "{")
  87. content = strings.TrimSpace(content)
  88. content = strings.Trim(content, "}")
  89. location := NgxLocation{
  90. Path: path,
  91. Content: content,
  92. }
  93. location.Comments = s.commentQueue.DequeueAllComments()
  94. s.Locations = append(s.Locations, location)
  95. }