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

