59
59
import com .ning .http .util .AsyncHttpProviderUtils ;
60
60
import com .ning .http .util .AuthenticatorUtils ;
61
61
import static com .ning .http .util .MiscUtil .isNonEmpty ;
62
- import static com .ning .http .util .MiscUtil .isNonEmpty ;
63
- import static com .ning .http .util .MiscUtil .isNonEmpty ;
64
62
65
63
import com .ning .http .util .ProxyUtils ;
66
64
import com .ning .http .util .SslUtils ;
@@ -561,18 +559,26 @@ static int getPort(final URI uri, final int p) {
561
559
562
560
563
561
@ SuppressWarnings ({"unchecked" })
564
- boolean sendRequest (final FilterChainContext ctx ,
565
- final Request request ,
562
+ boolean sendRequest (final HttpTransactionContext httpCtx ,
563
+ final FilterChainContext ctx ,
566
564
final HttpRequestPacket requestPacket ,
567
565
final BodyHandler bodyHandler )
568
566
throws IOException {
567
+
568
+ final Request request = httpCtx .request ;
569
+ final AsyncHandler h = httpCtx .handler ;
570
+ if (h instanceof TransferCompletionHandler ) {
571
+ final FluentCaseInsensitiveStringsMap map =
572
+ new FluentCaseInsensitiveStringsMap (request .getHeaders ());
573
+ TransferCompletionHandler .class .cast (h ).transferAdapter (new GrizzlyTransferAdapter (map ));
574
+ }
569
575
576
+ requestPacket .setConnection (ctx .getConnection ());
577
+
570
578
boolean isWriteComplete = true ;
571
579
572
580
if (bodyHandler != null ) { // Check if the HTTP request has body
573
- final HttpTransactionContext context = HttpTransactionContext .get (ctx .getConnection ());
574
-
575
- context .bodyHandler = bodyHandler ;
581
+ httpCtx .bodyHandler = bodyHandler ;
576
582
if (LOGGER .isDebugEnabled ()) {
577
583
LOGGER .debug ("REQUEST: " + requestPacket .toString ());
578
584
}
@@ -867,42 +873,36 @@ private boolean sendAsGrizzlyRequest(final Request request,
867
873
convertToUpgradeRequest (httpCtx );
868
874
}
869
875
final Request req = httpCtx .request ;
870
- final URI uri = req .isUseRawUrl () ? req .getRawURI () : req .getURI ();
871
876
final Method method = Method .valueOf (request .getMethod ());
872
- final HttpRequestPacket .Builder builder = HttpRequestPacket .builder ();
877
+ final URI uri = req .isUseRawUrl () ? req .getRawURI () : req .getURI ();
878
+
873
879
boolean secure = "https" .equals (uri .getScheme ());
874
- builder .method (method );
875
- builder .protocol (Protocol .HTTP_1_1 );
876
880
877
- if (!request .getHeaders ().containsKey (Header .Host .toString ())) {
878
- String host = request .getVirtualHost ();
879
- if (host != null ) {
880
- builder .header (Header .Host , host );
881
- } else {
882
- if (uri .getPort () == -1 ) {
883
- builder .header (Header .Host , uri .getHost ());
884
- } else {
885
- builder .header (Header .Host , uri .getHost () + ':' + uri .getPort ());
886
- }
887
- }
888
- }
889
881
final ProxyServer proxy = ProxyUtils .getProxyServer (config , request );
890
882
final boolean useProxy = proxy != null ;
883
+
884
+ final boolean isEstablishingConnectTunnel =
885
+ useProxy && (secure || httpCtx .isWSRequest ) &&
886
+ !httpCtx .isTunnelEstablished (connection );
891
887
888
+ if (isEstablishingConnectTunnel ) {
889
+ // once the tunnel is established, sendAsGrizzlyRequest will
890
+ // be called again and we'll finally send the request over the tunnel
891
+ return establishConnectTunnel (proxy , httpCtx , uri , ctx );
892
+ }
893
+
894
+ final HttpRequestPacket .Builder builder =
895
+ HttpRequestPacket .builder ()
896
+ .protocol (Protocol .HTTP_1_1 )
897
+ .method (method );
898
+
892
899
if (useProxy ) {
893
- if (secure || httpCtx .isWSRequest ) { // TUNNELING?
894
- if (!httpCtx .isTunnelEstablished (connection )) {
895
- secure = false ;
896
- httpCtx .establishingTunnel = true ;
897
- builder .method (Method .CONNECT );
898
- builder .uri (AsyncHttpProviderUtils .getAuthority (uri ));
900
+ if (secure || httpCtx .isWSRequest ) { // Sending message over established CONNECT tunnel
901
+ if (config .isUseRelativeURIsWithConnectProxies ()) {
902
+ builder .uri (uri .getRawPath ());
903
+ builder .query (uri .getRawQuery ());
899
904
} else {
900
- if (config .isUseRelativeURIsWithConnectProxies ()) {
901
- builder .uri (uri .getRawPath ());
902
- builder .query (uri .getRawQuery ());
903
- } else {
904
- builder .uri (uri .toString ());
905
- }
905
+ builder .uri (uri .toString ());
906
906
}
907
907
} else {
908
908
builder .uri (uri .toString ());
@@ -912,10 +912,11 @@ private boolean sendAsGrizzlyRequest(final Request request,
912
912
builder .query (uri .getRawQuery ());
913
913
}
914
914
915
- final BodyHandler bodyHandler = isPayloadAllowed (method ) ?
916
- bodyHandlerFactory .getBodyHandler (request ) :
917
- null ;
918
-
915
+ HttpRequestPacket requestPacket ;
916
+ final BodyHandler bodyHandler = isPayloadAllowed (method )
917
+ ? bodyHandlerFactory .getBodyHandler (request )
918
+ : null ;
919
+
919
920
if (bodyHandler != null ) {
920
921
final long contentLength = request .getContentLength ();
921
922
if (contentLength >= 0 ) {
@@ -925,53 +926,68 @@ private boolean sendAsGrizzlyRequest(final Request request,
925
926
builder .chunked (true );
926
927
}
927
928
}
928
-
929
- HttpRequestPacket requestPacket ;
930
- if (httpCtx .isWSRequest && !httpCtx .establishingTunnel ) {
929
+
930
+ if (httpCtx .isWSRequest ) {
931
931
try {
932
932
final URI wsURI = new URI (httpCtx .wsRequestURI );
933
933
secure = "wss" .equalsIgnoreCase (wsURI .getScheme ());
934
934
httpCtx .protocolHandler = Version .RFC6455 .createHandler (true );
935
935
httpCtx .handshake = httpCtx .protocolHandler .createHandShake (wsURI );
936
- requestPacket = (HttpRequestPacket )
937
- httpCtx .handshake .composeHeaders ().getHttpHeader ();
936
+ requestPacket = (HttpRequestPacket ) httpCtx .handshake .composeHeaders ().getHttpHeader ();
938
937
} catch (URISyntaxException e ) {
939
938
throw new IllegalArgumentException ("Invalid WS URI: " + httpCtx .wsRequestURI );
940
939
}
941
940
} else {
942
941
requestPacket = builder .build ();
943
942
}
944
- requestPacket .setSecure (secure );
945
943
944
+ requestPacket .setSecure (secure );
946
945
ctx .notifyDownstream (new SwitchingSSLFilter .SSLSwitchingEvent (secure , connection ));
947
946
948
- addHeaders (request , requestPacket );
947
+ copyHeaders (request , requestPacket );
949
948
addCookies (request , requestPacket );
950
- addAuthorizationHeader (request , requestPacket );
951
949
952
- if (useProxy ) {
953
- if (!requestPacket .getHeaders ().contains (Header .ProxyConnection )) {
954
- requestPacket .setHeader (Header .ProxyConnection , "keep-alive" );
955
- }
950
+ addServiceHeaders (requestPacket );
951
+ addHostHeaderIfNeeded (request , uri , requestPacket );
952
+ addAuthorizationHeader (getRealm (request ), requestPacket );
956
953
957
- if (proxy .getPrincipal () != null ) {
958
- requestPacket .setHeader (Header .ProxyAuthorization ,
959
- AuthenticatorUtils .computeBasicAuthentication (proxy ));
960
- }
961
- }
962
- final AsyncHandler h = httpCtx .handler ;
963
- if (h instanceof TransferCompletionHandler ) {
964
- final FluentCaseInsensitiveStringsMap map =
965
- new FluentCaseInsensitiveStringsMap (request .getHeaders ());
966
- TransferCompletionHandler .class .cast (h ).transferAdapter (new GrizzlyTransferAdapter (map ));
954
+ if (useProxy ) {
955
+ addProxyHeaders (proxy , requestPacket );
967
956
}
968
957
969
- requestPacket .setConnection (connection );
970
- return sendRequest (ctx , request , requestPacket ,
958
+ return sendRequest (httpCtx , ctx , requestPacket ,
971
959
wrapWithExpectHandlerIfNeeded (bodyHandler , requestPacket ));
972
960
973
961
}
974
962
963
+ private boolean establishConnectTunnel (
964
+ final ProxyServer proxy ,
965
+ final HttpTransactionContext httpCtx ,
966
+ final URI uri ,
967
+ final FilterChainContext ctx ) throws IOException {
968
+ final Connection connection = ctx .getConnection ();
969
+
970
+ final HttpRequestPacket requestPacket =
971
+ HttpRequestPacket .builder ()
972
+ .protocol (Protocol .HTTP_1_0 )
973
+ .method (Method .CONNECT )
974
+ .uri (AsyncHttpProviderUtils .getAuthority (uri ))
975
+ .build ();
976
+
977
+ httpCtx .establishingTunnel = true ;
978
+
979
+ // turn off SSL, because CONNECT will be sent in plain mode
980
+ ctx .notifyDownstream (new SwitchingSSLFilter .SSLSwitchingEvent (false , connection ));
981
+
982
+ final Request request = httpCtx .request ;
983
+ addServiceHeaders (requestPacket );
984
+ addHostHeaderIfNeeded (request , uri , requestPacket );
985
+ addAuthorizationHeader (getRealm (request ), requestPacket );
986
+ addProxyHeaders (proxy , requestPacket );
987
+
988
+ return sendRequest (httpCtx , ctx , requestPacket , null );
989
+ }
990
+
975
991
/**
976
992
* check if we need to wrap the BodyHandler with ExpectHandler
977
993
*/
@@ -997,11 +1013,7 @@ private boolean isPayloadAllowed(final Method method) {
997
1013
return method .getPayloadExpectation () != Method .PayloadExpectation .NOT_ALLOWED ;
998
1014
}
999
1015
1000
- private void addAuthorizationHeader (final Request request , final HttpRequestPacket requestPacket ) {
1001
- Realm realm = request .getRealm ();
1002
- if (realm == null ) {
1003
- realm = config .getRealm ();
1004
- }
1016
+ private void addAuthorizationHeader (final Realm realm , final HttpRequestPacket requestPacket ) {
1005
1017
if (realm != null && realm .getUsePreemptiveAuth ()) {
1006
1018
final String authHeaderValue = generateAuthHeader (realm );
1007
1019
if (authHeaderValue != null ) {
@@ -1010,6 +1022,40 @@ private void addAuthorizationHeader(final Request request, final HttpRequestPack
1010
1022
}
1011
1023
}
1012
1024
1025
+ private void addProxyHeaders (final ProxyServer proxy ,
1026
+ final HttpRequestPacket requestPacket )
1027
+ throws UnsupportedEncodingException {
1028
+
1029
+ if (!requestPacket .getHeaders ().contains (Header .ProxyConnection )) {
1030
+ requestPacket .setHeader (Header .ProxyConnection , "keep-alive" );
1031
+ }
1032
+
1033
+ if (proxy .getPrincipal () != null ) {
1034
+ requestPacket .setHeader (Header .ProxyAuthorization ,
1035
+ AuthenticatorUtils .computeBasicAuthentication (proxy ));
1036
+ }
1037
+ }
1038
+
1039
+ private void addHostHeaderIfNeeded (final Request request ,
1040
+ final URI uri , final HttpRequestPacket requestPacket ) {
1041
+ if (!requestPacket .containsHeader (Header .Host )) {
1042
+ String host = request .getVirtualHost ();
1043
+ if (host != null ) {
1044
+ requestPacket .addHeader (Header .Host , host );
1045
+ } else {
1046
+ if (uri .getPort () == -1 ) {
1047
+ requestPacket .addHeader (Header .Host , uri .getHost ());
1048
+ } else {
1049
+ requestPacket .addHeader (Header .Host , uri .getHost () + ':' + uri .getPort ());
1050
+ }
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ private Realm getRealm (final Request request ) {
1056
+ return request .getRealm () != null ? request .getRealm () : config .getRealm ();
1057
+ }
1058
+
1013
1059
private String generateAuthHeader (final Realm realm ) {
1014
1060
try {
1015
1061
switch (realm .getAuthScheme ()) {
@@ -1051,7 +1097,7 @@ private void convertToUpgradeRequest(final HttpTransactionContext ctx) {
1051
1097
ctx .requestUrl = sb .toString ();
1052
1098
}
1053
1099
1054
- private void addHeaders (final Request request ,
1100
+ private void copyHeaders (final Request request ,
1055
1101
final HttpRequestPacket requestPacket ) {
1056
1102
1057
1103
final FluentCaseInsensitiveStringsMap map = request .getHeaders ();
@@ -1066,7 +1112,9 @@ private void addHeaders(final Request request,
1066
1112
}
1067
1113
}
1068
1114
}
1069
-
1115
+ }
1116
+
1117
+ private void addServiceHeaders (final HttpRequestPacket requestPacket ) {
1070
1118
final MimeHeaders headers = requestPacket .getHeaders ();
1071
1119
if (!headers .contains (Header .Connection )) {
1072
1120
requestPacket .addHeader (Header .Connection , "keep-alive" );
@@ -1079,8 +1127,6 @@ private void addHeaders(final Request request,
1079
1127
if (!headers .contains (Header .UserAgent )) {
1080
1128
requestPacket .addHeader (Header .UserAgent , config .getUserAgent ());
1081
1129
}
1082
-
1083
-
1084
1130
}
1085
1131
1086
1132
0 commit comments