Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ jobs:
stack test --no-rerun-tests http-types:test:spec ${{ matrix.resolver }}
- name: Test Docs
run: |
stack test --no-rerun-tests http-types:test:doctests ${{ matrix.resolver }}
stack test http-types:test:doctests ${{ matrix.resolver }}
# # We probably want to add benchmarks at some point, just to make sure
# # functions don't regress in performance too much?
# - name: Bench
Expand Down
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
*~
.cabal-sandbox
cabal.sandbox.config
dist/*
dist-newstyle/*
dist/
dist-newstyle/
*_flymake.hs
*.lock
.stack-work/*
test/golden/*.actual
.stack-work/
test/.golden/**/actual
*.code-workspace
*.local
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@

## 0.12.5 [XXXX-XX-XX]

* Add status `451 Unavailable For Legal Reasons`
* Add `http30` as a shortcut for `HttpVersion 3 0`
* Export everything from `Network.HTTP.Types`
* Added a bunch of regression, unit and property tests for stability.
* Updated the `README.md`
* Lowest GHC version supported is now `7.10.3`.
Adjusted dependency constraints to reflect this.
* Removed explicit `Typeable` class derivations since that happens automatically
since GHC `7.10`

## 0.12.4 [2023-11-29]

* Add `Data` and `Generic` instances to `ByteRange`, `StdMethod`, `Status` and `HttpVersion`.
* Add `Data` and `Generic` instances to `ByteRange`, `StdMethod`, `Status`
and `HttpVersion`.
* Rework of all the documentation, with the addition of `@since` notations.

## 0.12.3 [2019-02-24]
Expand Down
3 changes: 3 additions & 0 deletions Network/HTTP/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module Network.HTTP.Types (
http10,
http11,
http20,
http30,

-- * Status

Expand Down Expand Up @@ -122,6 +123,8 @@ module Network.HTTP.Types (
tooManyRequests429,
status431,
requestHeaderFieldsTooLarge431,
status451,
unavailableForLegalReasons451,
status500,
internalServerError500,
status501,
Expand Down
22 changes: 13 additions & 9 deletions Network/HTTP/Types/Header.hs
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,6 @@ import qualified Data.ByteString.Lazy as BL
import qualified Data.CaseInsensitive as CI
import Data.Data (Data)
import Data.List (intersperse)
#if __GLASGOW_HASKELL__ < 710
import Data.Monoid
#endif
import GHC.Generics (Generic)

-- | A full HTTP header field with the name and value separated.
Expand Down Expand Up @@ -451,7 +448,9 @@ hPrefer = "Prefer"
hPreferenceApplied :: HeaderName
hPreferenceApplied = "Preference-Applied"

-- | An individual byte range.
-- | An individual byte range. Used in @Range@ request headers.
-- This type and its accompanying functions are /NOT/ compatible with the
-- @Content-Range@ response header.
--
-- Negative indices are not allowed!
--
Expand Down Expand Up @@ -554,8 +553,13 @@ parseByteRanges bs1 = do
(r, bs5) <- range bs4
ranges (front . (r :)) bs5

-- FIXME: Use 'stripPrefix' from the 'bytestring' package.
-- Might have to update the dependency constraints though.
stripPrefixB x y
| x `B.isPrefixOf` y = Just (B.drop (B.length x) y)
| otherwise = Nothing
stripPrefixB :: B.ByteString -> B.ByteString -> Maybe B.ByteString
#if !MIN_VERSION_bytestring(0,10,8)
-- FIXME: Use 'stripPrefix' from the 'bytestring' package.
-- Might have to update the dependency constraints though.
stripPrefixB x y
| x `B.isPrefixOf` y = Just (B.drop (B.length x) y)
| otherwise = Nothing
#else
stripPrefixB = B.stripPrefix
#endif
18 changes: 9 additions & 9 deletions Network/HTTP/Types/Method.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,39 +52,39 @@ import GHC.Generics (Generic)
-- | HTTP method (flat 'B.ByteString' type).
type Method = B.ByteString

-- | HTTP GET Method
-- | GET Method
methodGet :: Method
methodGet = renderStdMethod GET

-- | HTTP POST Method
-- | POST Method
methodPost :: Method
methodPost = renderStdMethod POST

-- | HTTP HEAD Method
-- | HEAD Method
methodHead :: Method
methodHead = renderStdMethod HEAD

-- | HTTP PUT Method
-- | PUT Method
methodPut :: Method
methodPut = renderStdMethod PUT

-- | HTTP DELETE Method
-- | DELETE Method
methodDelete :: Method
methodDelete = renderStdMethod DELETE

-- | HTTP TRACE Method
-- | TRACE Method
methodTrace :: Method
methodTrace = renderStdMethod TRACE

-- | HTTP CONNECT Method
-- | CONNECT Method
methodConnect :: Method
methodConnect = renderStdMethod CONNECT

-- | HTTP OPTIONS Method
-- | OPTIONS Method
methodOptions :: Method
methodOptions = renderStdMethod OPTIONS

-- | HTTP PATCH Method
-- | PATCH Method
--
-- @since 0.8.0
methodPatch :: Method
Expand Down
39 changes: 29 additions & 10 deletions Network/HTTP/Types/Status.hs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ module Network.HTTP.Types.Status (
tooManyRequests429,
status431,
requestHeaderFieldsTooLarge431,
status451,
unavailableForLegalReasons451,
status500,
internalServerError500,
status501,
Expand Down Expand Up @@ -221,6 +223,7 @@ instance Enum Status where
toEnum 428 = status428
toEnum 429 = status429
toEnum 431 = status431
toEnum 451 = status451
toEnum 500 = status500
toEnum 501 = status501
toEnum 502 = status502
Expand All @@ -236,6 +239,8 @@ instance Bounded Status where
maxBound = status511

-- | Create a 'Status' from a status code and message.
--
-- @since 0.7.3
mkStatus :: Int -> B.ByteString -> Status
mkStatus = Status

Expand Down Expand Up @@ -645,61 +650,75 @@ unprocessableEntity422 :: Status
unprocessableEntity422 = status422

-- | Upgrade Required 426
-- (<https://tools.ietf.org/html/rfc7231#section-6.5.15>)
-- (<https://tools.ietf.org/html/rfc7231#section-6.5.15 RFC 7231>)
--
-- @since 0.10
status426 :: Status
status426 = mkStatus 426 "Upgrade Required"

-- | Upgrade Required 426
-- (<https://tools.ietf.org/html/rfc7231#section-6.5.15>)
-- (<https://tools.ietf.org/html/rfc7231#section-6.5.15 RFC 7231>)
--
-- @since 0.10
upgradeRequired426 :: Status
upgradeRequired426 = status426

-- | Precondition Required 428
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-3 RFC 6585>)
--
-- @since 0.8.5
status428 :: Status
status428 = mkStatus 428 "Precondition Required"

-- | Precondition Required 428
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-3 RFC 6585>)
--
-- @since 0.8.5
preconditionRequired428 :: Status
preconditionRequired428 = status428

-- | Too Many Requests 429
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-4 RFC 6585>)
--
-- @since 0.8.5
status429 :: Status
status429 = mkStatus 429 "Too Many Requests"

-- | Too Many Requests 429
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-4 RFC 6585>)
--
-- @since 0.8.5
tooManyRequests429 :: Status
tooManyRequests429 = status429

-- | Request Header Fields Too Large 431
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-5 RFC 6585>)
--
-- @since 0.8.5
status431 :: Status
status431 = mkStatus 431 "Request Header Fields Too Large"

-- | Request Header Fields Too Large 431
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-5 RFC 6585>)
--
-- @since 0.8.5
requestHeaderFieldsTooLarge431 :: Status
requestHeaderFieldsTooLarge431 = status431

-- | Unavailable For Legal Reasons 451
-- (<https://tools.ietf.org/html/rfc7725 RFC 7725>)
--
-- @since 0.12.5
status451 :: Status
status451 = mkStatus 451 "Unavailable For Legal Reasons"

-- | Unavailable For Legal Reasons 451
-- (<https://tools.ietf.org/html/rfc7725 RFC 7725>)
--
-- @since 0.13
unavailableForLegalReasons451 :: Status
unavailableForLegalReasons451 = status451

-- | Internal Server Error 500
status500 :: Status
status500 = mkStatus 500 "Internal Server Error"
Expand Down Expand Up @@ -769,14 +788,14 @@ httpVersionNotSupported505 :: Status
httpVersionNotSupported505 = status505

-- | Network Authentication Required 511
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-6 RFC 6585>)
--
-- @since 0.8.5
status511 :: Status
status511 = mkStatus 511 "Network Authentication Required"

-- | Network Authentication Required 511
-- (<https://tools.ietf.org/html/rfc6585 RFC 6585>)
-- (<https://tools.ietf.org/html/rfc6585#section-6 RFC 6585>)
--
-- @since 0.8.5
networkAuthenticationRequired511 :: Status
Expand Down
11 changes: 7 additions & 4 deletions Network/HTTP/Types/URI.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@ import qualified Data.ByteString.Lazy as BL
import Data.Char (ord)
import Data.List (intersperse)
import Data.Maybe (fromMaybe)
#if __GLASGOW_HASKELL__ < 710
import Data.Monoid
#endif
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8With, encodeUtf8)
import Data.Text.Encoding.Error (lenientDecode)
Expand Down Expand Up @@ -275,6 +272,12 @@ ord8 :: Char -> Word8
ord8 = fromIntegral . ord

unreservedQS, unreservedPI :: [Word8]
-- FIXME: According to RFC 3986, the following are also allowed in query segments:
-- "!'()*;:@&=+$,/?"
--
-- https://www.rfc-editor.org/rfc/rfc3986#section-3.4
--
-- Incidentally, this is also the list of unreserved characters for fragments.
unreservedQS = map ord8 "-_.~"
-- FIXME: According to RFC 3986, the following are also allowed in path segments:
-- "!'()*;"
Expand Down Expand Up @@ -542,7 +545,7 @@ renderQueryPartialEscape qm =
-- @since 0.12.1
renderQueryBuilderPartialEscape :: Bool -> PartialEscapeQuery -> B.Builder
renderQueryBuilderPartialEscape _ [] = mempty
-- FIXME replace mconcat + map with foldr
-- FIXME: replace mconcat + map with foldr
renderQueryBuilderPartialEscape qmark' (p : ps) =
mconcat $
go (if qmark' then qmark else mempty) p
Expand Down
7 changes: 7 additions & 0 deletions Network/HTTP/Types/Version.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Network.HTTP.Types.Version (
http10,
http11,
http20,
http30,
) where

import Data.Data (Data)
Expand Down Expand Up @@ -51,3 +52,9 @@ http11 = HttpVersion 1 1
-- @since 0.10
http20 :: HttpVersion
http20 = HttpVersion 2 0

-- | HTTP 3.0
--
-- @since 0.12.5
http30 :: HttpVersion
http30 = HttpVersion 3 0
5 changes: 5 additions & 0 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
packages: ./http-types.cabal
ignore-project: False
allow-newer: Cabal-3.14.2.0:containers,
Cabal-syntax-3.14.2.0:containers
jobs: 2
8 changes: 5 additions & 3 deletions http-types.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ Synopsis: Generic HTTP types for Haskell (for both client and server
Description: Types and functions to describe and handle HTTP concepts.
Including "methods", "headers", "query strings", "paths" and "HTTP versions".
Homepage: https://github.com/Vlix/http-types
License: BSD3
License: BSD-3-Clause
License-file: LICENSE
Author: Aristid Breitkreuz, Michael Snoyman
Maintainer: felix.paulusma@gmail.com
Copyright: (C) 2011 Aristid Breitkreuz
Copyright: (C) 2011 Aristid Breitkreuz, (C) 2023 Felix Paulusma
Category: Network, Web
Build-type: Simple
Tested-with:
GHC == 7.10.3, GHC == 9.6.7, GHC == 9.8.4, GHC == 9.10.3, GHC == 9.12.4, GHC == 9.14.1
Extra-source-files:
README.md
CHANGELOG.md
Expand Down Expand Up @@ -60,7 +62,7 @@ Test-suite spec
case-insensitive,
filepath,
hspec >= 1.3,
hspec-golden,
hspec-golden >= 0.2,
http-types,
QuickCheck,
quickcheck-instances,
Expand Down
2 changes: 1 addition & 1 deletion test/Network/HTTP/Types/HeaderSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ headerCheck (hdr, msg) = do
it (B8.unpack . pad $ original msg) $ hdr `shouldBe` msg
where
pad bs =
let padding = B8.pack $ replicate (maxMsg - B.length bs) ' '
let padding = B8.replicate (maxMsg - B.length bs) ' '
in bs <> padding

maxMsg :: Int
Expand Down
3 changes: 2 additions & 1 deletion test/Network/HTTP/Types/StatusSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ _400Statusses =
, (status428, preconditionRequired428, 428, "Precondition Required")
, (status429, tooManyRequests429, 429, "Too Many Requests")
, (status431, requestHeaderFieldsTooLarge431, 431, "Request Header Fields Too Large")
, (status451, unavailableForLegalReasons451, 451, "Unavailable For Legal Reasons")
]

_500Statusses :: [StatusTuple]
Expand Down Expand Up @@ -131,7 +132,7 @@ statusCheck (st, st', code, msg) = do
st `shouldBe` st'
where
pad bs =
let padding = B8.pack $ replicate (maxMsg - B.length bs) ' '
let padding = B8.replicate (maxMsg - B.length bs) ' '
in bs <> padding

maxMsg :: Int
Expand Down
Loading
Loading