@@ -83,6 +83,8 @@ defmodule Mint.HTTP1 do
8383 """
8484 @ type error_reason ( ) :: term ( )
8585
86+ @ optional_responses_opts [ :status_reason ]
87+
8688 defstruct [
8789 :host ,
8890 :port ,
@@ -99,7 +101,8 @@ defmodule Mint.HTTP1 do
99101 buffer: "" ,
100102 proxy_headers: [ ] ,
101103 private: % { } ,
102- log: false
104+ log: false ,
105+ optional_responses: [ ]
103106 ]
104107
105108 defmacrop log ( conn , level , message ) do
@@ -128,6 +131,12 @@ defmodule Mint.HTTP1 do
128131 will not be validated. You might want this if you deal with non standard-
129132 conforming URIs but need to preserve them. The default is to validate the request
130133 target. *Available since v1.7.0*.
134+ * `:optional_responses` - (list of atoms) a list of optional responses to return.
135+ The possible values in the list are -
136+ * `:status_reason` which will return the
137+ [reason-phrase](https://datatracker.ietf.org/doc/html/rfc9112#name-status-line)
138+ for the status code, if it is returned by the server in status-line.
139+ This is only available for HTTP/1.1 connections. *Available since v1.7.2*.
131140
132141 """
133142 @ spec connect ( Types . scheme ( ) , Types . address ( ) , :inet . port_number ( ) , keyword ( ) ) ::
@@ -206,7 +215,8 @@ defmodule Mint.HTTP1 do
206215 state: :open ,
207216 log: log? ,
208217 case_sensitive_headers: Keyword . get ( opts , :case_sensitive_headers , false ) ,
209- skip_target_validation: Keyword . get ( opts , :skip_target_validation , false )
218+ skip_target_validation: Keyword . get ( opts , :skip_target_validation , false ) ,
219+ optional_responses: validate_optional_response_values ( opts )
210220 }
211221
212222 { :ok , conn }
@@ -217,6 +227,21 @@ defmodule Mint.HTTP1 do
217227 end
218228 end
219229
230+ defp validate_optional_response_values ( opts ) do
231+ opts
232+ |> Keyword . get ( :optional_responses , [ ] )
233+ |> Enum . map ( fn opt ->
234+ if opt not in @ optional_responses_opts do
235+ raise ArgumentError , """
236+ invalid :optional_responses value #{ opt } .
237+ allowed values are - #{ inspect ( @ optional_responses_opts ) }
238+ """
239+ end
240+
241+ opt
242+ end )
243+ end
244+
220245 @ doc """
221246 See `Mint.HTTP.close/1`.
222247 """
@@ -646,10 +671,10 @@ defmodule Mint.HTTP1 do
646671
647672 defp decode ( :status , % { request: request } = conn , data , responses ) do
648673 case Response . decode_status_line ( data ) do
649- { :ok , { version , status , _reason } , rest } ->
674+ { :ok , { version , status , _reason } = status_line , rest } ->
650675 request = % { request | version: version , status: status , state: :headers }
651676 conn = % { conn | request: request }
652- responses = [ { :status , request . ref , status } | responses ]
677+ responses = put_status_responses ( conn , status_line , responses )
653678 decode ( :headers , conn , rest , responses )
654679
655680 :more ->
@@ -872,6 +897,20 @@ defmodule Mint.HTTP1 do
872897 end
873898 end
874899
900+ defp put_status_responses (
901+ % { request: request , optional_responses: optional_responses } ,
902+ { _version , status , reason } ,
903+ responses
904+ ) do
905+ responses = [ { :status , request . ref , status } | responses ]
906+
907+ if Enum . member? ( optional_responses , :status_reason ) do
908+ [ { :status_reason , request . ref , reason } | responses ]
909+ else
910+ responses
911+ end
912+ end
913+
875914 defp store_header ( % { content_length: nil } = request , "content-length" , value ) do
876915 with { :ok , content_length } <- Parse . content_length_header ( value ) ,
877916 do: { :ok , % { request | content_length: content_length } }
0 commit comments