Control: tags -1 patch

Hi,

Please find the proposed fix/workaround for approx behind
HTTPS proxy which is using "HTTP CONNECT" method.

Is it possible to include it into default approx codebase?

P.S. the patch has been taken from GitHub:
> https://github.com/raol/approx-clone/commit/a767f6d1a29877e81e8db1a29d3fd00eda221c33

Thank you!

-- 
Alex Lutay
Head of Quality Assurance
Sipwise GmbH, Campus 21/Europaring F15
AT-2345 Brunn am Gebirge
>From a767f6d1a29877e81e8db1a29d3fd00eda221c33 Mon Sep 17 00:00:00 2001
From: Oleg Rakitskiy <[email protected]>
Date: Fri, 1 Nov 2019 00:03:20 +0100
Subject: [PATCH] Fix connection established response

small fix of the issue described here
https://bugs.debian.org/cgi-bin/bugreport.cgi\?bug\=914798
---
 approx.ml | 14 +++++++++-----
 url.ml    | 23 ++++++++++++++++++-----
 url.mli   |  6 ++++--
 3 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/approx.ml b/approx.ml
index c1f1c2c..643e3b9 100644
--- a/approx.ml
+++ b/approx.ml
@@ -277,11 +277,12 @@ let status_re = Pcre.regexp "^HTTP/\\d+(?:\\.\\d+)?\\s+(\\d{3})(?:\\s+(.*?)\\s*)
 let header_re = Pcre.regexp "^(.*?):\\s*(.*?)\\s*$"
 
 let process_header resp str =
-  let do_status (code, _) =
-    resp.status <- int_of_string code
+  let do_status (code, value) =
+    resp.status <- int_of_string code;
+    Url.STATUS (code, value)
   in
   let do_header (header, value) =
-    match String.lowercase header with
+    (match String.lowercase header with
     | "content-length" ->
         (try resp.length <- Int64.of_string value
          with Failure _ ->
@@ -296,13 +297,16 @@ let process_header resp str =
            error_message "Cannot parse Location %s" value)
     | "content-type" -> (* only used for pass-through content *)
         resp.content_type <- value
-    | _ -> ()
+    | _ -> ());
+    Url.OTHER
   in
   debug_message "  %s" str;
   try with_pair header_re str do_header
   with Not_found -> (* e.g., status line or CRLF *)
     try with_pair status_re str do_status
-    with Not_found -> error_message "Unrecognized response: %s" str
+    with Not_found -> (
+      error_message "Unrecognized response: %s" str;
+      Url.OTHER)
 
 (* Process a chunk of the response body.
    If no Content-Length was present in the header, we cache the whole
diff --git a/url.ml b/url.ml
index ac185f2..5493e63 100644
--- a/url.ml
+++ b/url.ml
@@ -38,6 +38,10 @@ let reverse_translate url =
 
 type protocol = HTTP | HTTPS | FTP | FILE
 
+type header = STATUS of string * string | OTHER
+
+type header_state = PROXY_RESPONSE | NORMAL
+
 let protocol url =
   try
     match String.lowercase (substring url ~until: (String.index url ':')) with
@@ -66,19 +70,28 @@ let iter_headers proc chan =
     try Some (input_line chan)
     with End_of_file -> None
   in
-  let rec loop () =
+  let rec loop state =
     match next () with
     | Some header ->
         let n = String.length header in
         if n > 0 && header.[n - 1] = '\r' then
-          if n > 1 then begin
-            proc (String.sub header 0 (n - 1));
-            loop ()
+          if n > 1 || state = PROXY_RESPONSE then begin (* Continue consuming input when we have response from proxy *)
+            match proc (String.sub header 0 (n - 1)) with
+            | STATUS (_,value) -> 
+              (* 
+                When we get reponse from the proxy "Connection established"
+                we switch to proxy mode and will ignore empty line delimiter
+                until we get next status header which will switch loop to normal mode.
+               *)
+              if String.lowercase value = "connection established" 
+              then loop PROXY_RESPONSE
+              else loop NORMAL
+            | OTHER -> loop state
           end else () (* CRLF terminates headers *)
         else error_message "Unexpected header: %s" header
     | None -> ()
   in
-  loop ()
+  loop NORMAL
 
 exception File_not_found
 exception Download_error
diff --git a/url.mli b/url.mli
index 420866a..d5abfad 100644
--- a/url.mli
+++ b/url.mli
@@ -13,6 +13,8 @@ val reverse_translate : string -> string
 
 type protocol = HTTP | HTTPS | FTP | FILE
 
+type header = STATUS of string * string | OTHER
+
 val protocol : string -> protocol
 
 exception File_not_found  (* raised when remote server returns 404 *)  
@@ -21,7 +23,7 @@ exception Download_error  (* raised when any other failure occurs *)
 (* Perform HTTP HEAD (or equivalent for FTP and FILE) on the given URL
    and apply a callback to each header that is returned *)
 
-val head : string -> (string -> unit) -> unit
+val head : string -> (string -> header) -> unit
 
 (* Download the specified URL with optional request headers,
    then apply callbacks to the headers and body chunks *)
@@ -29,7 +31,7 @@ val head : string -> (string -> unit) -> unit
 val download :
   string ->
   ?headers:string list ->
-  ?header_callback:(string -> unit) ->
+  ?header_callback:(string -> header) ->
   (string -> int -> int -> unit) -> unit
 
 (* Download a file from a remote repository *)
-- 
2.17.1

Reply via email to