diff --git a/src/Highlighter.php b/src/Highlighter.php
index 1961d6b..6c2236c 100644
--- a/src/Highlighter.php
+++ b/src/Highlighter.php
@@ -18,6 +18,7 @@
use Tempest\Highlight\Languages\Gdscript\GdscriptLanguage;
use Tempest\Highlight\Languages\Graphql\GraphqlLanguage;
use Tempest\Highlight\Languages\Html\HtmlLanguage;
+use Tempest\Highlight\Languages\Http\HttpLanguage;
use Tempest\Highlight\Languages\Ini\IniLanguage;
use Tempest\Highlight\Languages\JavaScript\JavaScriptLanguage;
use Tempest\Highlight\Languages\Json\JsonLanguage;
@@ -73,6 +74,7 @@ public function __construct(
->addLanguage(new GdscriptLanguage())
->addLanguage(new GraphqlLanguage())
->addLanguage(new HtmlLanguage())
+ ->addLanguage(new HttpLanguage())
->addLanguage(new JavaScriptLanguage())
->addLanguage(new JsonLanguage())
->addLanguage(new MarkdownLanguage())
diff --git a/src/Languages/Http/HttpLanguage.php b/src/Languages/Http/HttpLanguage.php
new file mode 100644
index 0000000..bb806bf
--- /dev/null
+++ b/src/Languages/Http/HttpLanguage.php
@@ -0,0 +1,51 @@
+(?m)^[A-Za-z][A-Za-z0-9-]*(?=\:))';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::ATTRIBUTE;
+ }
+}
diff --git a/src/Languages/Http/Patterns/HttpCommentPattern.php b/src/Languages/Http/Patterns/HttpCommentPattern.php
new file mode 100644
index 0000000..f283ce5
--- /dev/null
+++ b/src/Languages/Http/Patterns/HttpCommentPattern.php
@@ -0,0 +1,28 @@
+(?m)^(\/\/|\#).*)/';
+ }
+
+ public function getTokenType(): TokenType
+ {
+ return TokenTypeEnum::COMMENT;
+ }
+}
diff --git a/src/Languages/Http/Patterns/HttpMethodPattern.php b/src/Languages/Http/Patterns/HttpMethodPattern.php
new file mode 100644
index 0000000..cbc3ddd
--- /dev/null
+++ b/src/Languages/Http/Patterns/HttpMethodPattern.php
@@ -0,0 +1,28 @@
+(?m)^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS|CONNECT|TRACE)\b)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::KEYWORD;
+ }
+}
diff --git a/src/Languages/Http/Patterns/HttpStatusPattern.php b/src/Languages/Http/Patterns/HttpStatusPattern.php
new file mode 100644
index 0000000..7e6ccf1
--- /dev/null
+++ b/src/Languages/Http/Patterns/HttpStatusPattern.php
@@ -0,0 +1,30 @@
+\d{3})/';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::NUMBER;
+ }
+}
diff --git a/src/Languages/Http/Patterns/HttpUrlPattern.php b/src/Languages/Http/Patterns/HttpUrlPattern.php
new file mode 100644
index 0000000..db87aa0
--- /dev/null
+++ b/src/Languages/Http/Patterns/HttpUrlPattern.php
@@ -0,0 +1,27 @@
+\/[^\s]*|\w+:\/\/[^\s]*)(?=\sHTTP)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::VALUE;
+ }
+}
diff --git a/src/Languages/Http/Patterns/HttpVersionPattern.php b/src/Languages/Http/Patterns/HttpVersionPattern.php
new file mode 100644
index 0000000..edbf016
--- /dev/null
+++ b/src/Languages/Http/Patterns/HttpVersionPattern.php
@@ -0,0 +1,28 @@
+HTTP\/([32]|1\.[01]))';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::PROPERTY;
+ }
+}
diff --git a/tests/Bench/Fixtures/http.txt b/tests/Bench/Fixtures/http.txt
new file mode 100644
index 0000000..6b6445d
--- /dev/null
+++ b/tests/Bench/Fixtures/http.txt
@@ -0,0 +1,12 @@
+### Get all users
+GET https://api.example.com/users
+Accept: application/json
+
+### Create a new user
+POST https://api.example.com/users
+Content-Type: application/json
+
+{
+ "name": "Jane Doe",
+ "email": "jane@example.com"
+}
diff --git a/tests/Bench/HighlighterBench.php b/tests/Bench/HighlighterBench.php
index 30c17bd..f44f669 100644
--- a/tests/Bench/HighlighterBench.php
+++ b/tests/Bench/HighlighterBench.php
@@ -28,6 +28,7 @@ final class HighlighterBench
'gdscript' => 'gdscript.txt',
'graphql' => 'graphql.txt',
'html' => 'html.txt',
+ 'http' => 'http.txt',
'ini' => 'ini.txt',
'javascript' => 'javascript.txt',
'json' => 'json.txt',
diff --git a/tests/Languages/Http/HttpLanguageTest.php b/tests/Languages/Http/HttpLanguageTest.php
new file mode 100644
index 0000000..400d1c2
--- /dev/null
+++ b/tests/Languages/Http/HttpLanguageTest.php
@@ -0,0 +1,80 @@
+addLanguage(new HttpLanguage());
+
+ $this->assertSame(
+ trim($expected),
+ trim($highlighter->parse($content, 'http'))
+ );
+ }
+
+ public static function provide_highlighting_cases(): iterable
+ {
+ return [
+ // Standard Request Line
+ [
+ 'GET /index.html HTTP/1.1',
+ 'GET /index.html HTTP/1.1',
+ ],
+ // Request with absolute URL
+ [
+ 'POST https://api.tempest.php/v1/data HTTP/2',
+ 'POST https://api.tempest.php/v1/data HTTP/2',
+ ],
+ // Response Line
+ [
+ 'HTTP/1.1 200 OK',
+ 'HTTP/1.1 200 OK',
+ ],
+ // Headers
+ [
+ 'Host: localhost
+Content-Type: application/json
+X-Custom-Header: value',
+ 'Host: localhost
+Content-Type: application/json
+X-Custom-Header: value',
+ ],
+ // Full Request Example
+ [
+ "DELETE /user/1 HTTP/1.1\nHost: api.com\nAccept: */*",
+ "DELETE /user/1 HTTP/1.1\nHost: api.com\nAccept: */*",
+ ],
+ // Error Response
+ [
+ 'HTTP/2 404 Not Found',
+ 'HTTP/2 404 Not Found',
+ ],
+ // HTTP/3 response (highlight.js http3 fixture)
+ [
+ 'HTTP/3 200',
+ 'HTTP/3 200',
+ ],
+ // Three-digit header values must NOT be highlighted as a status code
+ [
+ "HTTP/2 301\ncontent-length: 220",
+ "HTTP/2 301\ncontent-length: 220",
+ ],
+ // Comments / request separators
+ [
+ '### Get users',
+ '',
+ ],
+ ];
+ }
+}
diff --git a/tests/targets/http.md b/tests/targets/http.md
new file mode 100644
index 0000000..1c7067f
--- /dev/null
+++ b/tests/targets/http.md
@@ -0,0 +1,11 @@
+```http
+### Get users
+POST https://api.example.com/users HTTP/1.1
+Content-Type: application/json
+
+HTTP/1.1 202 Accepted
+{
+ "name": "Jane Doe",
+ "email": "jane@example.com"
+}
+```