@@ -677,14 +677,22 @@ maybe_proxy(Transport, Scheme, Host, Port, Options)
677
677
end .
678
678
679
679
maybe_proxy_from_env (Transport , _Scheme , Host , Port , Options , true ) ->
680
- ? report_debug (" request without proxy" , []),
680
+ ? report_debug (" no proxy env is forced, request without proxy" , []),
681
681
hackney_connect :connect (Transport , Host , Port , Options , true );
682
682
maybe_proxy_from_env (Transport , Scheme , Host , Port , Options , _ ) ->
683
683
case get_proxy_env (Scheme ) of
684
684
{ok , Url } ->
685
- proxy_from_url (Url , Transport , Host , Port , Options );
685
+ NoProxyEnv = get_no_proxy_env (),
686
+ case match_no_proxy_env (NoProxyEnv , Host ) of
687
+ false ->
688
+ ? report_debug (" request with proxy" , [{proxy , Url }, {host , Host }]),
689
+ proxy_from_url (Url , Transport , Host , Port , Options );
690
+ true ->
691
+ ? report_debug (" request without proxy" , []),
692
+ hackney_connect :connect (Transport , Host , Port , Options , true )
693
+ end ;
686
694
false ->
687
- ? report_debug (" request without proxy" , []),
695
+ ? report_debug (" no proxy env setup, request without proxy" , []),
688
696
hackney_connect :connect (Transport , Host , Port , Options , true )
689
697
end .
690
698
@@ -706,17 +714,121 @@ proxy_from_url(Url, Transport, Host, Port, Options) ->
706
714
end
707
715
end .
708
716
717
+ get_no_proxy_env () ->
718
+ case application :get_env (hackney , no_proxy ) of
719
+ undefined ->
720
+ case get_no_proxy_env (? HTTP_NO_PROXY_ENV_VARS ) of
721
+ false ->
722
+ application :set_env (hackney , no_proxy , false ),
723
+ false ;
724
+ NoProxyEnv ->
725
+ parse_no_proxy_env (NoProxyEnv , [])
726
+ end ;
727
+ {ok , NoProxyEnv } ->
728
+ NoProxyEnv
729
+ end .
730
+
731
+ get_no_proxy_env ([Key | Rest ]) ->
732
+ case os :getenv (Key ) of
733
+ false -> get_no_proxy_env (Rest );
734
+ NoProxyStr ->
735
+ lists :usort (string :tokens (NoProxyStr , " ," ))
736
+ end ;
737
+ get_no_proxy_env ([]) ->
738
+ false .
739
+
740
+ parse_no_proxy_env ([" *" | _ ], _Acc ) ->
741
+ application :set_env (hackney , no_proxy , '*' ),
742
+ '*' ;
743
+ parse_no_proxy_env ([S | Rest ], Acc ) ->
744
+ try
745
+ CIDR = hackney_cidr :parse (S ),
746
+ parse_no_proxy_env (Rest , [{cidr , CIDR } | Acc ])
747
+ catch
748
+ _ :_ ->
749
+ Labels = string :tokens (S , " ." ),
750
+ parse_no_proxy_env (Rest , [{host , lists :reverse (Labels )}])
751
+ end ;
752
+ parse_no_proxy_env ([], Acc ) ->
753
+ NoProxy = lists :reverse (Acc ),
754
+ application :set_env (hackney , no_proxy , NoProxy ),
755
+ NoProxy .
756
+
757
+ match_no_proxy_env (false , _Host ) -> false ;
758
+ match_no_proxy_env ('*' , _Host ) -> true ;
759
+ match_no_proxy_env (Patterns , Host ) ->
760
+ do_match_no_proxy_env (Patterns , undefined , undefined , Host ).
761
+
762
+ do_match_no_proxy_env ([{cidr , _CIDR } | _ ]= Patterns , undefined , Labels , Host ) ->
763
+ Addrs = case inet :parse_address (Host ) of
764
+ {ok , Addr } -> [Addr ];
765
+ _ -> getaddrs (Host )
766
+ end ,
767
+ do_match_no_proxy_env (Patterns , Addrs , Labels , Host );
768
+ do_match_no_proxy_env ([{cidr , CIDR } | Rest ], Addrs , Labels , Host ) ->
769
+ case test_host_cidr (Addrs , CIDR ) of
770
+ true -> true ;
771
+ false -> do_match_no_proxy_env (Rest , Addrs , Labels , Host )
772
+ end ;
773
+ do_match_no_proxy_env ([{host , _Labels } | _ ] = Patterns , Addrs , undefined , Host ) ->
774
+ HostLabels = string :tokens (Host , " ." ),
775
+ do_match_no_proxy_env (Patterns , Addrs , lists :reverse (HostLabels ), Host );
776
+ do_match_no_proxy_env ([{host , Labels } | Rest ], Addrs , HostLabels , Host ) ->
777
+ case test_host_labels (Labels , HostLabels ) of
778
+ true -> true ;
779
+ false -> do_match_no_proxy_env (Rest , Addrs , Labels , Host )
780
+ end ;
781
+ do_match_no_proxy_env ([], _ , _ , _ ) ->
782
+ false .
783
+
784
+ test_host_labels ([" *" | R1 ], [_ | R2 ]) -> test_host_labels (R1 , R2 );
785
+ test_host_labels ([ A | R1 ], [A | R2 ]) -> test_host_labels (R1 , R2 );
786
+ test_host_labels ([], _ ) -> true ;
787
+ test_host_labels (_ , _ ) -> false .
788
+
789
+ test_host_cidr ([Addr , Rest ], CIDR ) ->
790
+ case hackney_cidr :contains (CIDR , Addr ) of
791
+ true -> true ;
792
+ false -> test_host_cidr (Rest , CIDR )
793
+ end ;
794
+ test_host_cidr ([], _ ) ->
795
+ false .
796
+
797
+ getaddrs (Host ) ->
798
+ IP4Addrs = case inet :getaddrs (Host , inet ) of
799
+ {ok , Addrs } -> Addrs ;
800
+ {error , nxdomain } -> []
801
+ end ,
802
+ case inet :getaddrs (Host , inet6 ) of
803
+ {ok , IP6Addrs } -> [IP6Addrs | IP4Addrs ];
804
+ {error , nxdomain } -> IP4Addrs
805
+ end .
806
+
709
807
get_proxy_env (https ) ->
710
- get_proxy_env (? HTTPS_PROXY_ENV_VARS );
808
+ case application :get_env (hackney , https_proxy ) of
809
+ undefined ->
810
+ ProxyEnv = do_get_proxy_env (? HTTPS_PROXY_ENV_VARS ),
811
+ application :set_env (hackney , https_proxy , ProxyEnv ),
812
+ ProxyEnv ;
813
+ {ok , Cached } ->
814
+ Cached
815
+ end ;
711
816
get_proxy_env (S ) when S =:= http ; S =:= http_unix ->
712
- get_proxy_env (? HTTP_PROXY_ENV_VARS );
817
+ case application :get_env (hackney , http_proxy ) of
818
+ undefined ->
819
+ ProxyEnv = do_get_proxy_env (? HTTP_PROXY_ENV_VARS ),
820
+ application :set_env (hackney , http_proxy , ProxyEnv ),
821
+ ProxyEnv ;
822
+ {ok , Cached } ->
823
+ Cached
824
+ end .
713
825
714
- get_proxy_env ([Var | Rest ]) ->
826
+ do_get_proxy_env ([Var | Rest ]) ->
715
827
case os :getenv (Var ) of
716
- false -> get_proxy_env (Rest );
828
+ false -> do_get_proxy_env (Rest );
717
829
Url -> {ok , Url }
718
830
end ;
719
- get_proxy_env ([]) ->
831
+ do_get_proxy_env ([]) ->
720
832
false .
721
833
722
834
do_connect (ProxyHost , ProxyPort , undefined , Transport , Host , Port , Options ) ->
0 commit comments