@@ -73,6 +73,11 @@ typedef struct {
7373 gitno_connection_data gitserver_data ;
7474 bool connected ;
7575
76+ /* Proxy */
77+ git_proxy_options proxy ;
78+ char * proxy_url ;
79+ gitno_connection_data proxy_data ;
80+
7681 /* Parser structures */
7782 http_parser parser ;
7883 http_parser_settings settings ;
@@ -203,7 +208,16 @@ static int gen_request(
203208 const char * path = t -> gitserver_data .path ? t -> gitserver_data .path : "/" ;
204209 size_t i ;
205210
206- git_buf_printf (buf , "%s %s%s HTTP/1.1\r\n" , s -> verb , path , s -> service_url );
211+ if (t -> proxy .type == GIT_PROXY_SPECIFIED )
212+ git_buf_printf (buf , "%s %s://%s:%s%s%s HTTP/1.1\r\n" ,
213+ s -> verb ,
214+ t -> gitserver_data .use_ssl ? "https" : "http" ,
215+ t -> gitserver_data .host ,
216+ t -> gitserver_data .port ,
217+ path , s -> service_url );
218+ else
219+ git_buf_printf (buf , "%s %s%s HTTP/1.1\r\n" ,
220+ s -> verb , path , s -> service_url );
207221
208222 git_buf_puts (buf , "User-Agent: " );
209223 git_http__user_agent (buf );
@@ -560,42 +574,56 @@ static int write_chunk(git_stream *io, const char *buffer, size_t len)
560574 return 0 ;
561575}
562576
563- static int apply_proxy_config (http_subtransport * t )
577+ static int apply_proxy_config_to_stream (http_subtransport * t )
564578{
565- int error ;
566- git_proxy_t proxy_type ;
567-
568- if (!git_stream_supports_proxy (t -> gitserver_stream ))
579+ /* Only set the proxy configuration on the curl stream. */
580+ if (!git_stream_supports_proxy (t -> gitserver_stream ) ||
581+ t -> proxy .type == GIT_PROXY_NONE )
569582 return 0 ;
570583
571- proxy_type = t -> owner -> proxy .type ;
584+ return git_stream_set_proxy (t -> gitserver_stream , & t -> proxy );
585+ }
572586
573- if (proxy_type == GIT_PROXY_NONE )
587+ static int load_proxy_config (http_subtransport * t )
588+ {
589+ int error ;
590+
591+ switch (t -> owner -> proxy .type ) {
592+ case GIT_PROXY_NONE :
574593 return 0 ;
575594
576- if (proxy_type == GIT_PROXY_AUTO ) {
577- char * url ;
578- git_proxy_options opts = GIT_PROXY_OPTIONS_INIT ;
595+ case GIT_PROXY_AUTO :
596+ git__free (t -> proxy_url );
597+ t -> proxy_url = NULL ;
598+
599+ git_proxy_init_options (& t -> proxy , GIT_PROXY_OPTIONS_VERSION );
579600
580- if ((error = git_remote__get_http_proxy (t -> owner -> owner , !!t -> gitserver_data .use_ssl , & url )) < 0 )
601+ if ((error = git_remote__get_http_proxy (t -> owner -> owner ,
602+ !!t -> gitserver_data .use_ssl , & t -> proxy_url )) < 0 )
581603 return error ;
582604
583- opts .credentials = t -> owner -> proxy .credentials ;
584- opts .certificate_check = t -> owner -> proxy .certificate_check ;
585- opts .payload = t -> owner -> proxy .payload ;
586- opts .type = GIT_PROXY_SPECIFIED ;
587- opts .url = url ;
588- error = git_stream_set_proxy (t -> gitserver_stream , & opts );
589- git__free (url );
605+ t -> proxy .type = GIT_PROXY_SPECIFIED ;
606+ t -> proxy .url = t -> proxy_url ;
607+ t -> proxy .credentials = t -> owner -> proxy .credentials ;
608+ t -> proxy .certificate_check = t -> owner -> proxy .certificate_check ;
609+ t -> proxy .payload = t -> owner -> proxy .payload ;
610+ break ;
590611
591- return error ;
612+ case GIT_PROXY_SPECIFIED :
613+ memcpy (& t -> proxy , & t -> owner -> proxy , sizeof (git_proxy_options ));
614+ break ;
615+
616+ default :
617+ assert (0 );
618+ return -1 ;
592619 }
593620
594- return git_stream_set_proxy ( t -> gitserver_stream , & t -> owner -> proxy );
621+ return gitno_connection_data_from_url ( & t -> proxy_data , t -> proxy . url , NULL );
595622}
596623
597624static int http_connect (http_subtransport * t )
598625{
626+ gitno_connection_data * connection_data ;
599627 int error ;
600628
601629 if (t -> connected &&
@@ -610,25 +638,27 @@ static int http_connect(http_subtransport *t)
610638 t -> connected = 0 ;
611639 }
612640
613- if (t -> gitserver_data .use_ssl ) {
614- error = git_tls_stream_new (& t -> gitserver_stream ,
615- t -> gitserver_data .host , t -> gitserver_data .port );
616- } else {
641+ connection_data = (t -> proxy .type == GIT_PROXY_SPECIFIED ) ?
642+ & t -> proxy_data : & t -> gitserver_data ;
643+
617644#ifdef GIT_CURL
618- error = git_curl_stream_new (& t -> gitserver_stream ,
619- t -> gitserver_data .host , t -> gitserver_data .port );
645+ error = git_curl_stream_new (& t -> gitserver_stream ,
646+ t -> gitserver_data .host , t -> gitserver_data .port );
620647#else
648+ if (connection_data -> use_ssl )
649+ error = git_tls_stream_new (& t -> gitserver_stream ,
650+ connection_data -> host , connection_data -> port );
651+ else
621652 error = git_socket_stream_new (& t -> gitserver_stream ,
622- t -> gitserver_data . host , t -> gitserver_data . port );
653+ connection_data -> host , connection_data -> port );
623654#endif
624- }
625655
626656 if (error < 0 )
627657 return error ;
628658
629659 GITERR_CHECK_VERSION (t -> gitserver_stream , GIT_STREAM_VERSION , "git_stream" );
630660
631- if ((error = apply_proxy_config (t )) < 0 )
661+ if ((error = apply_proxy_config_to_stream (t )) < 0 )
632662 return error ;
633663
634664 error = git_stream_connect (t -> gitserver_stream );
@@ -1020,11 +1050,22 @@ static int http_action(
10201050 http_subtransport * t = (http_subtransport * )subtransport ;
10211051 int ret ;
10221052
1023- if (!stream )
1024- return -1 ;
1053+ assert (stream );
10251054
1055+ /*
1056+ * If we've seen a redirect then preserve the location that we've
1057+ * been given. This is important to continue authorization against
1058+ * the redirect target, not the user-given source; the endpoint may
1059+ * have redirected us from HTTP->HTTPS and is using an auth mechanism
1060+ * that would be insecure in plaintext (eg, HTTP Basic).
1061+ */
10261062 if ((!t -> gitserver_data .host || !t -> gitserver_data .port || !t -> gitserver_data .path ) &&
1027- (ret = gitno_connection_data_from_url (& t -> gitserver_data , url , NULL )) < 0 )
1063+ (ret = gitno_connection_data_from_url (& t -> gitserver_data , url , NULL )) < 0 )
1064+ return ret ;
1065+
1066+ assert (t -> gitserver_data .host && t -> gitserver_data .port && t -> gitserver_data .path );
1067+
1068+ if ((ret = load_proxy_config (t )) < 0 )
10281069 return ret ;
10291070
10301071 if ((ret = http_connect (t )) < 0 )
@@ -1084,6 +1125,12 @@ static int http_close(git_smart_subtransport *subtransport)
10841125 gitno_connection_data_free_ptrs (& t -> gitserver_data );
10851126 memset (& t -> gitserver_data , 0x0 , sizeof (gitno_connection_data ));
10861127
1128+ gitno_connection_data_free_ptrs (& t -> proxy_data );
1129+ memset (& t -> proxy_data , 0x0 , sizeof (gitno_connection_data ));
1130+
1131+ git__free (t -> proxy_url );
1132+ t -> proxy_url = NULL ;
1133+
10871134 return 0 ;
10881135}
10891136
0 commit comments