@@ -17,6 +17,8 @@ have field names compatible with those expected by the `parse_status_line!` and
1717""" 
1818module  Parsers
1919
20+ import  .. access_threaded
21+ 
2022export  Header, Headers,
2123       find_end_of_header, find_end_of_chunk_size, find_end_of_trailer,
2224       parse_status_line!, parse_request_line!, parse_header_field,
@@ -49,17 +51,24 @@ ParseError(code::Symbol, bytes="") =
4951
5052#  Regular expressions for parsing HTTP start-line and header-fields
5153
54+ init! (r:: RegexAndMatchData ) =  (Base. compile (r. re); initialize! (r); r)
55+ 
5256""" 
5357https://tools.ietf.org/html/rfc7230#section-3.1.1 
5458request-line = method SP request-target SP HTTP-version CRLF 
5559""" 
56- const  request_line_regex =  [RegexAndMatchData (r""" ^
60+ const  request_line_regex =  RegexAndMatchData[]
61+ function  request_line_regex_f ()
62+     r =  RegexAndMatchData (r""" ^
5763    (?: \r ? \n ) ?                       #    ignore leading blank line 
5864    ([!#$%&'*+\- .^_`|~[:alnum:]]+) [ ]+ # 1. method = token (RFC7230 3.2.6) 
5965    ([^.][^ \r\n ]*) [ ]+                # 2. target 
6066    HTTP/(\d\.\d )                       # 3. version 
6167    \r ? \n                               #    CRLF 
62- """ x  )]
68+     """ x  )
69+     init! (r)
70+ end 
71+ 
6372
6473""" 
6574https://tools.ietf.org/html/rfc7230#section-3.1.2 
@@ -68,40 +77,58 @@ status-line = HTTP-version SP status-code SP reason-phrase CRLF
6877See: 
6978[#190](https://github.com/JuliaWeb/HTTP.jl/issues/190#issuecomment-363314009) 
7079""" 
71- const  status_line_regex =  [RegexAndMatchData (r""" ^
80+ const  status_line_regex =  RegexAndMatchData[]
81+ function  status_line_regex_f ()
82+     r =  RegexAndMatchData (r""" ^
7283    [ ]?                                # Issue #190 
7384    HTTP/(\d\.\d ) [ ]+                  # 1. version 
7485    (\d\d\d ) .*                         # 2. status 
7586    \r ? \n                               #    CRLF 
76- """ x  )]
87+     """ x  )
88+     init! (r)
89+ end 
7790
7891""" 
7992https://tools.ietf.org/html/rfc7230#section-3.2 
8093header-field = field-name ":" OWS field-value OWS 
8194""" 
82- const  header_field_regex =  [RegexAndMatchData (r""" ^
95+ const  header_field_regex =  RegexAndMatchData[]
96+ function  header_field_regex_f ()
97+     r =  RegexAndMatchData (r""" ^
8398    ([!#$%&'*+\- .^_`|~[:alnum:]]+) :    # 1. field-name = token (RFC7230 3.2.6) 
8499    [ \t ]*                              #    OWS 
85100    ([^\r\n ]*?)                         # 2. field-value 
86101    [ \t ]*                              #    OWS 
87102    \r ? \n                               #    CRLF 
88103    (?= [^ \t ])                         #    no WS on next line 
89- """ x  )]
104+     """ x  )
105+     init! (r)
106+ end 
107+ 
90108
91109""" 
92110https://tools.ietf.org/html/rfc7230#section-3.2.4 
93111obs-fold = CRLF 1*( SP / HTAB ) 
94112""" 
95- const  obs_fold_header_field_regex =  [RegexAndMatchData (r""" ^
113+ const  obs_fold_header_field_regex =  RegexAndMatchData[]
114+ function  obs_fold_header_field_regex_f ()
115+     r =  RegexAndMatchData (r""" ^
96116    ([!#$%&'*+\- .^_`|~[:alnum:]]+) :    # 1. field-name = token (RFC7230 3.2.6) 
97117    [ \t ]*                              #    OWS 
98118    ([^\r\n ]*                           # 2. field-value 
99119        (?: \r ? \n  [ \t ] [^\r\n ]*)*)    #    obs-fold 
100120    [ \t ]*                              #    OWS 
101121    \r ? \n                               #    CRLF 
102- """ x  )]
122+     """ x  )
123+     init! (r)
124+ end 
125+ 
126+ const  empty_header_field_regex =  RegexAndMatchData[]
127+ function  empty_header_field_regex_f ()
128+     r =  RegexAndMatchData (r" ^ \r ? \n " x  )
129+     init! (r)
130+ end 
103131
104- const  empty_header_field_regex =  [RegexAndMatchData (r" ^ \r ? \n " x  )]
105132
106133#  HTTP start-line and header-field parsing
107134
@@ -157,7 +184,7 @@ Parse HTTP request-line `bytes` and set the
157184Return a `SubString` containing the header-field lines. 
158185""" 
159186function  parse_request_line! (bytes:: AbstractString , request):: SubString{String} 
160-     re =  request_line_regex[Threads . threadid ()] 
187+     re =  access_threaded (request_line_regex_f, request_line_regex) 
161188    if  ! exec (re, bytes)
162189        throw (ParseError (:INVALID_REQUEST_LINE , bytes))
163190    end 
@@ -173,7 +200,7 @@ Parse HTTP response-line `bytes` and set the
173200Return a `SubString` containing the header-field lines. 
174201""" 
175202function  parse_status_line! (bytes:: AbstractString , response):: SubString{String} 
176-     re =  status_line_regex[Threads . threadid ()] 
203+     re =  access_threaded (status_line_regex_f, status_line_regex) 
177204    if  ! exec (re, bytes)
178205        throw (ParseError (:INVALID_STATUS_LINE , bytes))
179206    end 
@@ -189,20 +216,20 @@ a `SubString` containing the remaining header-field lines.
189216""" 
190217function  parse_header_field (bytes:: SubString{String} ):: Tuple{Header,SubString{String}} 
191218    #  First look for: field-name ":" field-value
192-     re =  header_field_regex[Threads . threadid ()] 
219+     re =  access_threaded (header_field_regex_f, header_field_regex) 
193220    if  exec (re, bytes)
194221        return  (group (1 , re, bytes) =>  group (2 , re, bytes)),
195222                nextbytes (re, bytes)
196223    end 
197224
198225    #  Then check for empty termination line:
199-     re =  empty_header_field_regex[Threads . threadid ()] 
226+     re =  access_threaded (empty_header_field_regex_f, empty_header_field_regex) 
200227    if  exec (re, bytes)
201228        return  emptyheader, nextbytes (re, bytes)
202229    end 
203230
204231    #  Finally look for obsolete line folding format:
205-     re =  obs_fold_header_field_regex[Threads . threadid ()] 
232+     re =  access_threaded (obs_fold_header_field_regex_f, obs_fold_header_field_regex) 
206233    if  exec (re, bytes)
207234        unfold =  SubString (replace (group (2 , re, bytes), r" \r ?\n " => " "  ))
208235        return  (group (1 , re, bytes) =>  unfold), nextbytes (re, bytes)
@@ -312,21 +339,11 @@ const unhex = Int8[
312339function  __init__ ()
313340    #  FIXME  Consider turing off `PCRE.UTF` in `Regex.compile_options`
314341    #  https://github.com/JuliaLang/julia/pull/26731#issuecomment-380676770
315-     Threads. resize_nthreads! (status_line_regex)
316-     Threads. resize_nthreads! (request_line_regex)
317-     Threads. resize_nthreads! (header_field_regex)
318-     Threads. resize_nthreads! (obs_fold_header_field_regex)
319-     Threads. resize_nthreads! (empty_header_field_regex)
320-     foreach (x ->  Base. compile (x. re), status_line_regex)
321-     foreach (x ->  Base. compile (x. re), request_line_regex)
322-     foreach (x ->  Base. compile (x. re), header_field_regex)
323-     foreach (x ->  Base. compile (x. re), empty_header_field_regex)
324-     foreach (x ->  Base. compile (x. re), obs_fold_header_field_regex)
325-     foreach (initialize!, status_line_regex)
326-     foreach (initialize!, request_line_regex)
327-     foreach (initialize!, header_field_regex)
328-     foreach (initialize!, empty_header_field_regex)
329-     foreach (initialize!, obs_fold_header_field_regex)
342+     resize! (empty! (status_line_regex),           Threads. nthreads ())
343+     resize! (empty! (request_line_regex),          Threads. nthreads ())
344+     resize! (empty! (header_field_regex),          Threads. nthreads ())
345+     resize! (empty! (obs_fold_header_field_regex), Threads. nthreads ())
346+     resize! (empty! (empty_header_field_regex),    Threads. nthreads ())
330347    return 
331348end 
332349
0 commit comments