diff --git a/components/prism-http.js b/components/prism-http.js index e2d9df4504..868d8dd8cf 100644 --- a/components/prism-http.js +++ b/components/prism-http.js @@ -90,7 +90,16 @@ var pattern = suffixTypes[contentType] ? getSuffixPattern(contentType) : contentType; options[contentType.replace(/\//g, '-')] = { - pattern: RegExp('(content-type:\\s*' + pattern + '(?:(?:\\r\\n?|\\n).+)*)(?:\\r?\\n|\\r){2}[\\s\\S]*', 'i'), + pattern: RegExp( + '(' + /content-type:\s*/.source + pattern + /(?:(?:\r\n?|\n)[\w-].*)*(?:\r(?:\n|(?!\n))|\n)/.source + ')' + + // This is a little interesting: + // The HTTP format spec required 1 empty line before the body to make everything unambiguous. + // However, when writing code by hand (e.g. to display on a website) people can forget about this, + // so we want to be liberal here. We will allow the empty line to be omitted if the first line of + // the body does not start with a [\w-] character (as headers do). + /[^\w-][\s\S]*/.source, + 'i' + ), lookbehind: true, inside: httpLanguages[contentType] }; diff --git a/components/prism-http.min.js b/components/prism-http.min.js index 4445ec2e52..4a2cf98be2 100644 --- a/components/prism-http.min.js +++ b/components/prism-http.min.js @@ -1 +1 @@ -!function(t){t.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},"header-name":{pattern:/^[\w-]+:(?=.)/m,alias:"keyword"}};var a,e,s,n=t.languages,r={"application/javascript":n.javascript,"application/json":n.json||n.javascript,"application/xml":n.xml,"text/xml":n.xml,"text/html":n.html,"text/css":n.css},i={"application/json":!0,"application/xml":!0};for(var p in r)if(r[p]){a=a||{};var o=i[p]?(void 0,s=(e=p).replace(/^[a-z]+\//,""),"(?:"+e+"|\\w+/(?:[\\w.-]+\\+)+"+s+"(?![+\\w.-]))"):p;a[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+o+"(?:(?:\\r\\n?|\\n).+)*)(?:\\r?\\n|\\r){2}[\\s\\S]*","i"),lookbehind:!0,inside:r[p]}}a&&t.languages.insertBefore("http","header-name",a)}(Prism); \ No newline at end of file +!function(t){t.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},"header-name":{pattern:/^[\w-]+:(?=.)/m,alias:"keyword"}};var a,e,n,s=t.languages,i={"application/javascript":s.javascript,"application/json":s.json||s.javascript,"application/xml":s.xml,"text/xml":s.xml,"text/html":s.html,"text/css":s.css},r={"application/json":!0,"application/xml":!0};for(var p in i)if(i[p]){a=a||{};var o=r[p]?(void 0,n=(e=p).replace(/^[a-z]+\//,""),"(?:"+e+"|\\w+/(?:[\\w.-]+\\+)+"+n+"(?![+\\w.-]))"):p;a[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+o+"(?:(?:\r\n?|\n)[\\w-].*)*(?:\r(?:\n|(?!\n))|\n))[^\\w-][^]*","i"),lookbehind:!0,inside:i[p]}}a&&t.languages.insertBefore("http","header-name",a)}(Prism); \ No newline at end of file diff --git a/tests/languages/css+http/css_inclusion.test b/tests/languages/css+http/css_inclusion.test index 381ee3f387..addcdae95b 100644 --- a/tests/languages/css+http/css_inclusion.test +++ b/tests/languages/css+http/css_inclusion.test @@ -8,14 +8,17 @@ a.link:hover { [ ["header-name", "Content-type:"], - " text/css", + " text/css\r\n", + ["text-css", [ ["selector", "a.link:hover"], ["punctuation", "{"], + ["property", "color"], ["punctuation", ":"], " red", ["punctuation", ";"], + ["punctuation", "}"] ]] ] diff --git a/tests/languages/javascript+http/issue2733.test b/tests/languages/javascript+http/issue2733.test index aa07a46d5a..c6aec61357 100644 --- a/tests/languages/javascript+http/issue2733.test +++ b/tests/languages/javascript+http/issue2733.test @@ -43,7 +43,8 @@ transfer-encoding: chunked " timeout=60\r\n", ["header-name", "transfer-encoding:"], - " chunked", + " chunked\r\n", + ["application-json", [ ["punctuation", "{"], diff --git a/tests/languages/javascript+http/javascript_inclusion.test b/tests/languages/javascript+http/javascript_inclusion.test index 32aa765330..b20003dadb 100644 --- a/tests/languages/javascript+http/javascript_inclusion.test +++ b/tests/languages/javascript+http/javascript_inclusion.test @@ -6,7 +6,8 @@ var a = true; [ ["header-name", "Content-type:"], - " application/javascript", + " application/javascript\r\n", + ["application-javascript", [ ["keyword", "var"], " a ", diff --git a/tests/languages/json+http/issue2733.test b/tests/languages/json+http/issue2733.test index 024da6bbd1..04ece3e82a 100644 --- a/tests/languages/json+http/issue2733.test +++ b/tests/languages/json+http/issue2733.test @@ -43,7 +43,8 @@ transfer-encoding: chunked " timeout=60\r\n", ["header-name", "transfer-encoding:"], - " chunked", + " chunked\r\n", + ["application-json", [ ["punctuation", "{"], @@ -109,4 +110,4 @@ transfer-encoding: chunked ["punctuation", "}"] ]] -] \ No newline at end of file +] diff --git a/tests/languages/json+http/issue3168.test b/tests/languages/json+http/issue3168.test new file mode 100644 index 0000000000..03e32462ab --- /dev/null +++ b/tests/languages/json+http/issue3168.test @@ -0,0 +1,145 @@ +HTTP/1.1 200 OK +Access-Control-Allow-Credentials: true +Access-Control-Allow-Origin: * +Connection: keep-alive +Content-Length: 523 +Content-Type: application/json +Server: gunicorn/19.9.0 +X-Kong-Proxy-Latency: 1 +X-Kong-Upstream-Latency: 1 +{ + "args": {}, + "data": "", + "files": {}, + "form": {}, + "headers": { + "Accept": "*/*", + "Accept-Encoding": "gzip, deflate", + "Connection": "close", + "Host": "httpbin.org", + "User-Agent": "HTTPie/1.0.2", + "X-Forwarded-Host": "example.com" + }, + "json": null, + "method": "GET", + "origin": "172.19.0.1, 52.201.239.166", + "url": "http://example.com/anything" +} + +---------------------------------------------------- + +[ + ["response-status", [ + ["http-version", "HTTP/1.1"], + ["status-code", "200"], + ["reason-phrase", "OK"] + ]], + + ["header-name", "Access-Control-Allow-Credentials:"], + " true\r\n", + + ["header-name", "Access-Control-Allow-Origin:"], + " *\r\n", + + ["header-name", "Connection:"], + " keep-alive\r\n", + + ["header-name", "Content-Length:"], + " 523\r\n", + + ["header-name", "Content-Type:"], + " application/json\r\n", + + ["header-name", "Server:"], + " gunicorn/19.9.0\r\n", + + ["header-name", "X-Kong-Proxy-Latency:"], + " 1\r\n", + + ["header-name", "X-Kong-Upstream-Latency:"], + " 1\r\n", + + ["application-json", [ + ["punctuation", "{"], + + ["property", "\"args\""], + ["operator", ":"], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", ","], + + ["property", "\"data\""], + ["operator", ":"], + ["string", "\"\""], + ["punctuation", ","], + + ["property", "\"files\""], + ["operator", ":"], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", ","], + + ["property", "\"form\""], + ["operator", ":"], + ["punctuation", "{"], + ["punctuation", "}"], + ["punctuation", ","], + + ["property", "\"headers\""], + ["operator", ":"], + ["punctuation", "{"], + + ["property", "\"Accept\""], + ["operator", ":"], + ["string", "\"*/*\""], + ["punctuation", ","], + + ["property", "\"Accept-Encoding\""], + ["operator", ":"], + ["string", "\"gzip, deflate\""], + ["punctuation", ","], + + ["property", "\"Connection\""], + ["operator", ":"], + ["string", "\"close\""], + ["punctuation", ","], + + ["property", "\"Host\""], + ["operator", ":"], + ["string", "\"httpbin.org\""], + ["punctuation", ","], + + ["property", "\"User-Agent\""], + ["operator", ":"], + ["string", "\"HTTPie/1.0.2\""], + ["punctuation", ","], + + ["property", "\"X-Forwarded-Host\""], + ["operator", ":"], + ["string", "\"example.com\""], + + ["punctuation", "}"], + ["punctuation", ","], + + ["property", "\"json\""], + ["operator", ":"], + ["null", "null"], + ["punctuation", ","], + + ["property", "\"method\""], + ["operator", ":"], + ["string", "\"GET\""], + ["punctuation", ","], + + ["property", "\"origin\""], + ["operator", ":"], + ["string", "\"172.19.0.1, 52.201.239.166\""], + ["punctuation", ","], + + ["property", "\"url\""], + ["operator", ":"], + ["string", "\"http://example.com/anything\""], + + ["punctuation", "}"] + ]] +] diff --git a/tests/languages/json+http/json-suffix_inclusion.test b/tests/languages/json+http/json-suffix_inclusion.test index 0cb82163c8..e977d6169e 100644 --- a/tests/languages/json+http/json-suffix_inclusion.test +++ b/tests/languages/json+http/json-suffix_inclusion.test @@ -6,7 +6,8 @@ Content-type: application/x.foo+bar+json [ ["header-name", "Content-type:"], - " application/x.foo+bar+json", + " application/x.foo+bar+json\r\n", + ["application-json", [ ["punctuation", "{"], ["property", "\"foo\""], diff --git a/tests/languages/json+http/json_inclusion.test b/tests/languages/json+http/json_inclusion.test index d680a6b261..a2d6855ba0 100644 --- a/tests/languages/json+http/json_inclusion.test +++ b/tests/languages/json+http/json_inclusion.test @@ -6,7 +6,8 @@ Content-type: application/json [ ["header-name", "Content-type:"], - " application/json", + " application/json\r\n", + ["application-json", [ ["punctuation", "{"], ["property", "\"foo\""], diff --git a/tests/languages/markup+http/html_inclusion.test b/tests/languages/markup+http/html_inclusion.test index a0d9d975ba..ff284721cc 100644 --- a/tests/languages/markup+http/html_inclusion.test +++ b/tests/languages/markup+http/html_inclusion.test @@ -6,7 +6,8 @@ Content-type: text/html [ ["header-name", "Content-type:"], - " text/html", + " text/html\r\n", + ["text-html", [ ["tag", [ ["tag", [ diff --git a/tests/languages/markup+http/issue2733.test b/tests/languages/markup+http/issue2733.test index 01b7c2b5d2..c706f60ff6 100644 --- a/tests/languages/markup+http/issue2733.test +++ b/tests/languages/markup+http/issue2733.test @@ -32,7 +32,8 @@ transfer-encoding: chunked " timeout=60\r\n", ["header-name", "transfer-encoding:"], - " chunked", + " chunked\r\n", + ["application-xml", [ ["tag", [ ["tag", [ @@ -82,4 +83,4 @@ transfer-encoding: chunked ["punctuation", ">"] ]] ]] -] \ No newline at end of file +] diff --git a/tests/languages/markup+http/text-xml_inclusion.test b/tests/languages/markup+http/text-xml_inclusion.test index ecc0c71c6b..6712da66e4 100644 --- a/tests/languages/markup+http/text-xml_inclusion.test +++ b/tests/languages/markup+http/text-xml_inclusion.test @@ -6,7 +6,8 @@ Content-type: text/xml [ ["header-name", "Content-type:"], - " text/xml", + " text/xml\r\n", + ["text-xml", [ ["tag", [ ["tag", [ diff --git a/tests/languages/markup+http/xml-suffix_inclusion.test b/tests/languages/markup+http/xml-suffix_inclusion.test index 82b9df450b..cdef47f564 100644 --- a/tests/languages/markup+http/xml-suffix_inclusion.test +++ b/tests/languages/markup+http/xml-suffix_inclusion.test @@ -6,7 +6,8 @@ Content-type: text/x.anything+something-else+xml [ ["header-name", "Content-type:"], - " text/x.anything+something-else+xml", + " text/x.anything+something-else+xml\r\n", + ["application-xml", [ ["tag", [ ["tag", [ diff --git a/tests/languages/markup+http/xml_inclusion.test b/tests/languages/markup+http/xml_inclusion.test index 36f2dfea17..45987a1b18 100644 --- a/tests/languages/markup+http/xml_inclusion.test +++ b/tests/languages/markup+http/xml_inclusion.test @@ -6,7 +6,8 @@ Content-type: application/xml [ ["header-name", "Content-type:"], - " application/xml", + " application/xml\r\n", + ["application-xml", [ ["tag", [ ["tag", [