[{"data":1,"prerenderedAt":1362},["ShallowReactive",2],{"Categories":3,"NavIndexCategoriesCountFooter":203,"content-\u002F2020\u002F12\u002F09\u002Fmitmproxy-with-java\u002F":204},[4,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,68,70,71,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202],{"category":5},"System Administration",{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},"Software Development",{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":27},{"category":27},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":5},{"category":27},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":27},{"category":27},{"category":67},"Drones & RC",{"category":69},"DIY Projects",{"category":67},{"category":72},"Photography",{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":69},{"category":67},{"category":69},{"category":69},{"category":67},{"category":67},{"category":72},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":5},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":5},{"category":67},{"category":67},{"category":72},{"category":72},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":67},{"category":72},{"category":67},{"category":138},"3D Printing - Laser Cutting - CNC",{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":138},{"category":5},{"category":138},{"category":27},{"category":27},{"category":138},{"category":138},{"category":72},{"category":158},"Photography,3D Printing - Laser Cutting - CNC",{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":5},{"category":67},{"category":5},{"category":5},{"category":27},{"category":27},{"category":27},{"category":27},{"category":27},{"category":69},{"category":27},{"category":27},{"category":27},{"category":27},{"category":181},"Home Assistant",{"category":181},{"category":72},{"category":27},{"category":27},{"category":72},{"category":138},{"category":5},{"category":72},{"category":72},{"category":138},{"category":27},{"category":181},{"category":181},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},{"category":72},191,{"id":205,"title":206,"body":207,"category":27,"date":1350,"description":213,"embedImage":1351,"extension":1352,"image":334,"intro":1353,"meta":1354,"navigation":504,"path":1355,"seo":1356,"series":1351,"sitemap":1357,"stem":1358,"tags":1359,"__hash__":1361},"content\u002F2020\u002F12\u002F09\u002Fmitmproxy-with-java.md","mitmproxy with java",{"type":208,"value":209,"toc":1343},"minimark",[210,214,228,231,239,244,247,250,275,278,281,307,310,317,320,323,329,335,341,347,356,360,363,366,369,373,376,597,600,746,749,767,770,773,776,779,782,785,818,825,828,847,850,856,860,863,871,879,882,1095,1098,1312,1318,1324,1328,1331,1339],[211,212,213],"p",{},"I recently had the need to inspect what a java application was actually sending over the wire including the body content on an https connection.",[211,215,216,217,227],{},"Let's look at how we can achieve that with ",[218,219,226],"a",{"href":220,"rel":221,"target":225},"https:\u002F\u002Fmitmproxy.org\u002F",[222,223,224],"nofollow","noopener","noreferer","_blank","mitmproxy",".",[211,229,230],{},"mitmproxy runs as an http proxy with both terminal and web inspection interfaces.",[211,232,233,234],{},"Installation is just a case of following the mitmproxy site instructions for your OS - or if you prefer - you can run it inside a ",[218,235,238],{"href":236,"rel":237,"target":225},"https:\u002F\u002Fhub.docker.com\u002Fr\u002Fmitmproxy\u002Fmitmproxy",[222,223,224],"docker image",[240,241,243],"h2",{"id":242},"browser-proxy","Browser proxy",[211,245,246],{},"First step is to get mitmproxy up and running.",[211,248,249],{},"To start the command line version on port 8899:",[251,252,257],"pre",{"className":253,"code":254,"language":255,"meta":256,"style":256},"language-shell shiki shiki-themes github-dark","mitmproxy --listen-port 8899\n","shell","",[258,259,260],"code",{"__ignoreMap":256},[261,262,265,268,272],"span",{"class":263,"line":264},"line",1,[261,266,226],{"class":267},"svObZ",[261,269,271],{"class":270},"sDLfK"," --listen-port",[261,273,274],{"class":270}," 8899\n",[211,276,277],{},"The first time it runs it will also create a set of certificates including a CA certificate. We will need these to intercept https traffic and the testing client (web browser or whatever) will have to trust the mitm CA certificate.",[211,279,280],{},"Once its running - to test that it works:",[251,282,284],{"className":253,"code":283,"language":255,"meta":256,"style":256},"curl --proxy 127.0.0.1:8899 --cacert ~\u002F.mitmproxy\u002Fmitmproxy-ca-cert.pem https:\u002F\u002Fwww.chrissearle.org\n",[258,285,286],{"__ignoreMap":256},[261,287,288,291,294,298,301,304],{"class":263,"line":264},[261,289,290],{"class":267},"curl",[261,292,293],{"class":270}," --proxy",[261,295,297],{"class":296},"sU2Wk"," 127.0.0.1:8899",[261,299,300],{"class":270}," --cacert",[261,302,303],{"class":296}," ~\u002F.mitmproxy\u002Fmitmproxy-ca-cert.pem",[261,305,306],{"class":296}," https:\u002F\u002Fwww.chrissearle.org\n",[211,308,309],{},"In the mitmproxy terminal there should be one flow now shown",[211,311,312],{},[313,314],"img",{"alt":315,"src":316},"mitmproxy flow from curl","\u002Fimages\u002Fposts\u002F2020\u002F12\u002Fmitm-curl-flow.png",[211,318,319],{},"Using the arrow keys (up\u002Fdown) to select a line - hitting enter drills down.",[211,321,322],{},"There are three views (left\u002Fright arrow to navigate).",[211,324,325],{},[313,326],{"alt":327,"src":328},"mitmproxy curl request","\u002Fimages\u002Fposts\u002F2020\u002F12\u002Fmitm-curl-request.png",[211,330,331],{},[313,332],{"alt":333,"src":334},"mitmproxy curl response","\u002Fimages\u002Fposts\u002F2020\u002F12\u002Fmitm-curl-response.png",[211,336,337],{},[313,338],{"alt":339,"src":340},"mitmproxy curl details","\u002Fimages\u002Fposts\u002F2020\u002F12\u002Fmitm-curl-detail.png",[211,342,343,344],{},"To get back to the flow list - just hit ",[258,345,346],{},"q",[211,348,349,350,355],{},"So - mitmproxy is working as expected. To use this with a real browser just set it as your browser's proxy (remember that the browser will have to trust the mitmproxy CA certificate - more on that on ",[218,351,354],{"href":352,"rel":353,"target":225},"https:\u002F\u002Fdocs.mitmproxy.org\u002Fstable\u002Fconcepts-certificates\u002F",[222,223,224],"mitmproxy docs",")",[240,357,359],{"id":358},"java","Java",[211,361,362],{},"mitmproxy is now working as a browser proxy. Time to try it out in java.",[211,364,365],{},"Many java web frameworks can use the system properties http.proxyHost, http.proxyPort, https.proxyHost and https.proxyPort.",[211,367,368],{},"But - two of the clients that I use need a little more work to set up a proxy.",[240,370,372],{"id":371},"java-httpclient-proxy","Java HttpClient proxy",[211,374,375],{},"First - call get with no proxy:",[251,377,380],{"className":378,"code":379,"language":358,"meta":256,"style":256},"language-java shiki shiki-themes github-dark","public class ProxyTest {\n  public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {\n    HttpRequest request = HttpRequest.newBuilder()\n        .uri(new URI(\"https:\u002F\u002Fwww.chrissearle.org\"))\n        .GET()\n        .build();\n\n    HttpClient client = HttpClient.newBuilder().build();\n\n    HttpResponse\u003CString> response =\n        client.send(request, HttpResponse.BodyHandlers.ofString());\n\n    System.out.println(response.body());\n  }\n}\n",[258,381,382,398,435,453,478,488,499,506,526,531,545,563,568,585,591],{"__ignoreMap":256},[261,383,384,388,391,394],{"class":263,"line":264},[261,385,387],{"class":386},"snl16","public",[261,389,390],{"class":386}," class",[261,392,393],{"class":267}," ProxyTest",[261,395,397],{"class":396},"s95oV"," {\n",[261,399,401,404,407,410,413,416,419,422,426,429,432],{"class":263,"line":400},2,[261,402,403],{"class":386},"  public",[261,405,406],{"class":386}," static",[261,408,409],{"class":386}," void",[261,411,412],{"class":267}," main",[261,414,415],{"class":396},"(",[261,417,418],{"class":386},"String",[261,420,421],{"class":396},"[] ",[261,423,425],{"class":424},"s9osk","args",[261,427,428],{"class":396},") ",[261,430,431],{"class":386},"throws",[261,433,434],{"class":396}," URISyntaxException, IOException, InterruptedException {\n",[261,436,438,441,444,447,450],{"class":263,"line":437},3,[261,439,440],{"class":396},"    HttpRequest request ",[261,442,443],{"class":386},"=",[261,445,446],{"class":396}," HttpRequest.",[261,448,449],{"class":267},"newBuilder",[261,451,452],{"class":396},"()\n",[261,454,456,459,462,464,467,470,472,475],{"class":263,"line":455},4,[261,457,458],{"class":396},"        .",[261,460,461],{"class":267},"uri",[261,463,415],{"class":396},[261,465,466],{"class":386},"new",[261,468,469],{"class":267}," URI",[261,471,415],{"class":396},[261,473,474],{"class":296},"\"https:\u002F\u002Fwww.chrissearle.org\"",[261,476,477],{"class":396},"))\n",[261,479,481,483,486],{"class":263,"line":480},5,[261,482,458],{"class":396},[261,484,485],{"class":267},"GET",[261,487,452],{"class":396},[261,489,491,493,496],{"class":263,"line":490},6,[261,492,458],{"class":396},[261,494,495],{"class":267},"build",[261,497,498],{"class":396},"();\n",[261,500,502],{"class":263,"line":501},7,[261,503,505],{"emptyLinePlaceholder":504},true,"\n",[261,507,509,512,514,517,519,522,524],{"class":263,"line":508},8,[261,510,511],{"class":396},"    HttpClient client ",[261,513,443],{"class":386},[261,515,516],{"class":396}," HttpClient.",[261,518,449],{"class":267},[261,520,521],{"class":396},"().",[261,523,495],{"class":267},[261,525,498],{"class":396},[261,527,529],{"class":263,"line":528},9,[261,530,505],{"emptyLinePlaceholder":504},[261,532,534,537,539,542],{"class":263,"line":533},10,[261,535,536],{"class":396},"    HttpResponse\u003C",[261,538,418],{"class":386},[261,540,541],{"class":396},"> response ",[261,543,544],{"class":386},"=\n",[261,546,548,551,554,557,560],{"class":263,"line":547},11,[261,549,550],{"class":396},"        client.",[261,552,553],{"class":267},"send",[261,555,556],{"class":396},"(request, HttpResponse.BodyHandlers.",[261,558,559],{"class":267},"ofString",[261,561,562],{"class":396},"());\n",[261,564,566],{"class":263,"line":565},12,[261,567,505],{"emptyLinePlaceholder":504},[261,569,571,574,577,580,583],{"class":263,"line":570},13,[261,572,573],{"class":396},"    System.out.",[261,575,576],{"class":267},"println",[261,578,579],{"class":396},"(response.",[261,581,582],{"class":267},"body",[261,584,562],{"class":396},[261,586,588],{"class":263,"line":587},14,[261,589,590],{"class":396},"  }\n",[261,592,594],{"class":263,"line":593},15,[261,595,596],{"class":396},"}\n",[211,598,599],{},"Then - modify to use the default proxy (which reads the above system properties):",[251,601,603],{"className":378,"code":602,"language":358,"meta":256,"style":256},"  public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {\n    HttpRequest request = HttpRequest.newBuilder()\n        .uri(new URI(\"https:\u002F\u002Fwww.chrissearle.org\"))\n        .GET()\n        .build();\n\n    HttpClient client = HttpClient.newBuilder().proxy(ProxySelector.getDefault()).build();\n\n    HttpResponse\u003CString> response =\n        client.send(request, HttpResponse.BodyHandlers.ofString());\n\n    System.out.println(response.body());\n  }\n",[258,604,605,622,634,652,660,668,672,700,704,714,726,730,742],{"__ignoreMap":256},[261,606,607,609,611,613,615,617,619],{"class":263,"line":264},[261,608,403],{"class":386},[261,610,406],{"class":386},[261,612,409],{"class":386},[261,614,412],{"class":267},[261,616,415],{"class":396},[261,618,418],{"class":386},[261,620,621],{"class":396},"[] args) throws URISyntaxException, IOException, InterruptedException {\n",[261,623,624,626,628,630,632],{"class":263,"line":400},[261,625,440],{"class":396},[261,627,443],{"class":386},[261,629,446],{"class":396},[261,631,449],{"class":267},[261,633,452],{"class":396},[261,635,636,638,640,642,644,646,648,650],{"class":263,"line":437},[261,637,458],{"class":396},[261,639,461],{"class":267},[261,641,415],{"class":396},[261,643,466],{"class":386},[261,645,469],{"class":267},[261,647,415],{"class":396},[261,649,474],{"class":296},[261,651,477],{"class":396},[261,653,654,656,658],{"class":263,"line":455},[261,655,458],{"class":396},[261,657,485],{"class":267},[261,659,452],{"class":396},[261,661,662,664,666],{"class":263,"line":480},[261,663,458],{"class":396},[261,665,495],{"class":267},[261,667,498],{"class":396},[261,669,670],{"class":263,"line":490},[261,671,505],{"emptyLinePlaceholder":504},[261,673,674,676,678,680,682,684,687,690,693,696,698],{"class":263,"line":501},[261,675,511],{"class":396},[261,677,443],{"class":386},[261,679,516],{"class":396},[261,681,449],{"class":267},[261,683,521],{"class":396},[261,685,686],{"class":267},"proxy",[261,688,689],{"class":396},"(ProxySelector.",[261,691,692],{"class":267},"getDefault",[261,694,695],{"class":396},"()).",[261,697,495],{"class":267},[261,699,498],{"class":396},[261,701,702],{"class":263,"line":508},[261,703,505],{"emptyLinePlaceholder":504},[261,705,706,708,710,712],{"class":263,"line":528},[261,707,536],{"class":396},[261,709,418],{"class":386},[261,711,541],{"class":396},[261,713,544],{"class":386},[261,715,716,718,720,722,724],{"class":263,"line":533},[261,717,550],{"class":396},[261,719,553],{"class":267},[261,721,556],{"class":396},[261,723,559],{"class":267},[261,725,562],{"class":396},[261,727,728],{"class":263,"line":547},[261,729,505],{"emptyLinePlaceholder":504},[261,731,732,734,736,738,740],{"class":263,"line":565},[261,733,573],{"class":396},[261,735,576],{"class":267},[261,737,579],{"class":396},[261,739,582],{"class":267},[261,741,562],{"class":396},[261,743,744],{"class":263,"line":570},[261,745,590],{"class":396},[211,747,748],{},"However - if you now run this with",[251,750,752],{"className":253,"code":751,"language":255,"meta":256,"style":256},"java -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8899 ProxyTest\n",[258,753,754],{"__ignoreMap":256},[261,755,756,758,761,764],{"class":263,"line":264},[261,757,358],{"class":267},[261,759,760],{"class":270}," -Dhttps.proxyHost=localhost",[261,762,763],{"class":270}," -Dhttps.proxyPort=8899",[261,765,766],{"class":296}," ProxyTest\n",[211,768,769],{},"You will find that you get an SSL error - PKIX path building failed",[211,771,772],{},"This is because we also need to tell java about the mitmproxy CA certificate.",[211,774,775],{},"This is done by adding the certificate to the truststore of the JVM.",[211,777,778],{},"The location of this file depends on what OS, what java version, what java installation method etc. In my case - I'm testing with adoptopenjdk 11 under sdkman - so I found the cacerts file under $SDKMAN-DOR\u002Fcandidates\u002Fjava\u002F11.0.9.hs-adpt\u002Flib\u002Fsecurity",[211,780,781],{},"I don't want to modify this in place - so - I copied the cacerts file local to the project.",[211,783,784],{},"We then need to import the mitmproxy CA:",[251,786,788],{"className":253,"code":787,"language":255,"meta":256,"style":256},"keytool -import -trustcacerts -file ~\u002F.mitmproxy\u002Fmitmproxy-ca-cert.pem -alias mitmproxycert -keystore cacerts\n",[258,789,790],{"__ignoreMap":256},[261,791,792,795,798,801,804,806,809,812,815],{"class":263,"line":264},[261,793,794],{"class":267},"keytool",[261,796,797],{"class":270}," -import",[261,799,800],{"class":270}," -trustcacerts",[261,802,803],{"class":270}," -file",[261,805,303],{"class":296},[261,807,808],{"class":270}," -alias",[261,810,811],{"class":296}," mitmproxycert",[261,813,814],{"class":270}," -keystore",[261,816,817],{"class":296}," cacerts\n",[211,819,820,821,824],{},"The default password for keystores is ",[258,822,823],{},"changeit"," - and then when it asks you if you wish to trust the certificate - say yes.",[211,826,827],{},"Now we can test again - this time setting the truststore system property:",[251,829,831],{"className":253,"code":830,"language":255,"meta":256,"style":256},"java -Dhttps.proxyHost=localhost -Dhttps.proxyPort=8899 -DProxyTest  -Djavax.net.ssl.trustStore=cacerts\n",[258,832,833],{"__ignoreMap":256},[261,834,835,837,839,841,844],{"class":263,"line":264},[261,836,358],{"class":267},[261,838,760],{"class":270},[261,840,763],{"class":270},[261,842,843],{"class":270}," -DProxyTest",[261,845,846],{"class":270},"  -Djavax.net.ssl.trustStore=cacerts\n",[211,848,849],{},"This time the command should complete and we should now see the call in the mitmproxy flow list",[211,851,852],{},[313,853],{"alt":854,"src":855},"mitmproxy java httpclient request","\u002Fimages\u002Fposts\u002F2020\u002F12\u002Fmitm-java-httpclient-request.png",[240,857,859],{"id":858},"java-spring-webclient-proxy-netty","Java Spring WebClient proxy (netty)",[211,861,862],{},"A fair number of projects I work on are spring boot based, using the reactive webclient - and the underlying netty library.",[211,864,865,866,870],{},"For this - we will use a maven project generated at ",[218,867,868],{"href":868,"rel":869,"target":225},"https:\u002F\u002Fstart.spring.io\u002F",[222,223,224]," (java 11\u002Fmaven\u002Fspring boot 2.4.0) with one added dependency - Spring Reactive Web.",[211,872,873,874],{},"This generates a ",[875,876],"download",{"path":877,"title":878},"\u002Ffiles\u002Fposts\u002F2020\u002F12\u002Fpom.xml","pom file",[211,880,881],{},"Just to make things simple - we'll make this a command line app and just call the request synchronously in run - first without the proxy:",[251,883,885],{"className":378,"code":884,"language":358,"meta":256,"style":256},"@SpringBootApplication\npublic class ProxytestApplication implements CommandLineRunner {\n\n    public static void main(String[] args) {\n        SpringApplication.run(ProxytestApplication.class, args);\n    }\n\n    @Override\n    public void run(String... args) throws Exception {\n        WebClient client = WebClient.builder().baseUrl(\"https:\u002F\u002Fwww.chrissearle.org\").build();\n\n        String page = client\n                .get()\n                .retrieve()\n                .bodyToMono(String.class)\n        .block();\n\n        System.out.println(page);\n    }\n}\n",[258,886,887,895,912,916,938,949,954,958,966,987,1016,1020,1030,1040,1049,1059,1069,1074,1085,1090],{"__ignoreMap":256},[261,888,889,892],{"class":263,"line":264},[261,890,891],{"class":396},"@",[261,893,894],{"class":386},"SpringBootApplication\n",[261,896,897,899,901,904,907,910],{"class":263,"line":400},[261,898,387],{"class":386},[261,900,390],{"class":386},[261,902,903],{"class":267}," ProxytestApplication",[261,905,906],{"class":386}," implements",[261,908,909],{"class":267}," CommandLineRunner",[261,911,397],{"class":396},[261,913,914],{"class":263,"line":437},[261,915,505],{"emptyLinePlaceholder":504},[261,917,918,921,923,925,927,929,931,933,935],{"class":263,"line":455},[261,919,920],{"class":386},"    public",[261,922,406],{"class":386},[261,924,409],{"class":386},[261,926,412],{"class":267},[261,928,415],{"class":396},[261,930,418],{"class":386},[261,932,421],{"class":396},[261,934,425],{"class":424},[261,936,937],{"class":396},") {\n",[261,939,940,943,946],{"class":263,"line":480},[261,941,942],{"class":396},"        SpringApplication.",[261,944,945],{"class":267},"run",[261,947,948],{"class":396},"(ProxytestApplication.class, args);\n",[261,950,951],{"class":263,"line":490},[261,952,953],{"class":396},"    }\n",[261,955,956],{"class":263,"line":501},[261,957,505],{"emptyLinePlaceholder":504},[261,959,960,963],{"class":263,"line":508},[261,961,962],{"class":396},"    @",[261,964,965],{"class":386},"Override\n",[261,967,968,970,972,975,978,980,982,984],{"class":263,"line":528},[261,969,920],{"class":386},[261,971,409],{"class":386},[261,973,974],{"class":267}," run",[261,976,977],{"class":396},"(String... ",[261,979,425],{"class":424},[261,981,428],{"class":396},[261,983,431],{"class":386},[261,985,986],{"class":396}," Exception {\n",[261,988,989,992,994,997,1000,1002,1005,1007,1009,1012,1014],{"class":263,"line":533},[261,990,991],{"class":396},"        WebClient client ",[261,993,443],{"class":386},[261,995,996],{"class":396}," WebClient.",[261,998,999],{"class":267},"builder",[261,1001,521],{"class":396},[261,1003,1004],{"class":267},"baseUrl",[261,1006,415],{"class":396},[261,1008,474],{"class":296},[261,1010,1011],{"class":396},").",[261,1013,495],{"class":267},[261,1015,498],{"class":396},[261,1017,1018],{"class":263,"line":547},[261,1019,505],{"emptyLinePlaceholder":504},[261,1021,1022,1025,1027],{"class":263,"line":565},[261,1023,1024],{"class":396},"        String page ",[261,1026,443],{"class":386},[261,1028,1029],{"class":396}," client\n",[261,1031,1032,1035,1038],{"class":263,"line":570},[261,1033,1034],{"class":396},"                .",[261,1036,1037],{"class":267},"get",[261,1039,452],{"class":396},[261,1041,1042,1044,1047],{"class":263,"line":587},[261,1043,1034],{"class":396},[261,1045,1046],{"class":267},"retrieve",[261,1048,452],{"class":396},[261,1050,1051,1053,1056],{"class":263,"line":593},[261,1052,1034],{"class":396},[261,1054,1055],{"class":267},"bodyToMono",[261,1057,1058],{"class":396},"(String.class)\n",[261,1060,1062,1064,1067],{"class":263,"line":1061},16,[261,1063,458],{"class":396},[261,1065,1066],{"class":267},"block",[261,1068,498],{"class":396},[261,1070,1072],{"class":263,"line":1071},17,[261,1073,505],{"emptyLinePlaceholder":504},[261,1075,1077,1080,1082],{"class":263,"line":1076},18,[261,1078,1079],{"class":396},"        System.out.",[261,1081,576],{"class":267},[261,1083,1084],{"class":396},"(page);\n",[261,1086,1088],{"class":263,"line":1087},19,[261,1089,953],{"class":396},[261,1091,1093],{"class":263,"line":1092},20,[261,1094,596],{"class":396},[211,1096,1097],{},"Now - let's add the proxy to the client instance. Here the host and port are hard coded but you could set them in application.properties or even read the system properties used above - all depending on what your app needs.",[251,1099,1101],{"className":378,"code":1100,"language":358,"meta":256,"style":256},"  public void run(String... args) throws Exception {\n    HttpClient httpClient = HttpClient.create()\n        .tcpConfiguration(tcpClient ->\n                tcpClient.proxy(proxy -> {\n                  proxy.type(ProxyProvider.Proxy.HTTP).address(new InetSocketAddress(\"localhost\", 8899));\n                }));\n\n        ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);\n\n    WebClient client = WebClient.builder().clientConnector(connector).baseUrl(\"https:\u002F\u002Fwww.chrissearle.org\").build();\n\n    String page = client\n        .get()\n        .retrieve()\n        .bodyToMono(String.class)\n        .block();\n\n    System.out.println(page);\n  }\n",[258,1102,1103,1114,1128,1141,1156,1191,1196,1200,1216,1220,1251,1255,1264,1272,1280,1288,1296,1300,1308],{"__ignoreMap":256},[261,1104,1105,1107,1109,1111],{"class":263,"line":264},[261,1106,403],{"class":386},[261,1108,409],{"class":386},[261,1110,974],{"class":267},[261,1112,1113],{"class":396},"(String... args) throws Exception {\n",[261,1115,1116,1119,1121,1123,1126],{"class":263,"line":400},[261,1117,1118],{"class":396},"    HttpClient httpClient ",[261,1120,443],{"class":386},[261,1122,516],{"class":396},[261,1124,1125],{"class":267},"create",[261,1127,452],{"class":396},[261,1129,1130,1132,1135,1138],{"class":263,"line":437},[261,1131,458],{"class":396},[261,1133,1134],{"class":267},"tcpConfiguration",[261,1136,1137],{"class":396},"(tcpClient ",[261,1139,1140],{"class":386},"->\n",[261,1142,1143,1146,1148,1151,1154],{"class":263,"line":455},[261,1144,1145],{"class":396},"                tcpClient.",[261,1147,686],{"class":267},[261,1149,1150],{"class":396},"(proxy ",[261,1152,1153],{"class":386},"->",[261,1155,397],{"class":396},[261,1157,1158,1161,1164,1167,1170,1172,1174,1177,1179,1182,1185,1188],{"class":263,"line":480},[261,1159,1160],{"class":396},"                  proxy.",[261,1162,1163],{"class":267},"type",[261,1165,1166],{"class":396},"(ProxyProvider.Proxy.HTTP).",[261,1168,1169],{"class":267},"address",[261,1171,415],{"class":396},[261,1173,466],{"class":386},[261,1175,1176],{"class":267}," InetSocketAddress",[261,1178,415],{"class":396},[261,1180,1181],{"class":296},"\"localhost\"",[261,1183,1184],{"class":396},", ",[261,1186,1187],{"class":270},"8899",[261,1189,1190],{"class":396},"));\n",[261,1192,1193],{"class":263,"line":490},[261,1194,1195],{"class":396},"                }));\n",[261,1197,1198],{"class":263,"line":501},[261,1199,505],{"emptyLinePlaceholder":504},[261,1201,1202,1205,1207,1210,1213],{"class":263,"line":508},[261,1203,1204],{"class":396},"        ReactorClientHttpConnector connector ",[261,1206,443],{"class":386},[261,1208,1209],{"class":386}," new",[261,1211,1212],{"class":267}," ReactorClientHttpConnector",[261,1214,1215],{"class":396},"(httpClient);\n",[261,1217,1218],{"class":263,"line":528},[261,1219,505],{"emptyLinePlaceholder":504},[261,1221,1222,1225,1227,1229,1231,1233,1236,1239,1241,1243,1245,1247,1249],{"class":263,"line":533},[261,1223,1224],{"class":396},"    WebClient client ",[261,1226,443],{"class":386},[261,1228,996],{"class":396},[261,1230,999],{"class":267},[261,1232,521],{"class":396},[261,1234,1235],{"class":267},"clientConnector",[261,1237,1238],{"class":396},"(connector).",[261,1240,1004],{"class":267},[261,1242,415],{"class":396},[261,1244,474],{"class":296},[261,1246,1011],{"class":396},[261,1248,495],{"class":267},[261,1250,498],{"class":396},[261,1252,1253],{"class":263,"line":547},[261,1254,505],{"emptyLinePlaceholder":504},[261,1256,1257,1260,1262],{"class":263,"line":565},[261,1258,1259],{"class":396},"    String page ",[261,1261,443],{"class":386},[261,1263,1029],{"class":396},[261,1265,1266,1268,1270],{"class":263,"line":570},[261,1267,458],{"class":396},[261,1269,1037],{"class":267},[261,1271,452],{"class":396},[261,1273,1274,1276,1278],{"class":263,"line":587},[261,1275,458],{"class":396},[261,1277,1046],{"class":267},[261,1279,452],{"class":396},[261,1281,1282,1284,1286],{"class":263,"line":593},[261,1283,458],{"class":396},[261,1285,1055],{"class":267},[261,1287,1058],{"class":396},[261,1289,1290,1292,1294],{"class":263,"line":1061},[261,1291,458],{"class":396},[261,1293,1066],{"class":267},[261,1295,498],{"class":396},[261,1297,1298],{"class":263,"line":1071},[261,1299,505],{"emptyLinePlaceholder":504},[261,1301,1302,1304,1306],{"class":263,"line":1076},[261,1303,573],{"class":396},[261,1305,576],{"class":267},[261,1307,1084],{"class":396},[261,1309,1310],{"class":263,"line":1087},[261,1311,590],{"class":396},[211,1313,1314,1315],{},"Again - if we run this then we get a PKIX path error - so we need to remember to add the truststore ",[258,1316,1317],{},"-Djavax.net.ssl.trustStore=cacerts",[211,1319,1320],{},[313,1321],{"alt":1322,"src":1323},"mitmproxy netty request","\u002Fimages\u002Fposts\u002F2020\u002F12\u002Fmitm-netty-request.png",[240,1325,1327],{"id":1326},"summary","Summary",[211,1329,1330],{},"So - mitmproxy can be used to show the decrypted https stream when debugging (if we'd used a post call instead of get then the request part of the mitmproxy output contains this in cleartext).",[211,1332,1333,1334],{},"mitmproxy can do a lot more - modification, replay, and has a bunch of addons - for more info - ",[218,1335,1338],{"href":1336,"rel":1337,"target":225},"https:\u002F\u002Fdocs.mitmproxy.org\u002Fstable\u002F",[222,223,224],"the mitmproxy docs",[1340,1341,1342],"style",{},"html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":256,"searchDepth":400,"depth":400,"links":1344},[1345,1346,1347,1348,1349],{"id":242,"depth":400,"text":243},{"id":358,"depth":400,"text":359},{"id":371,"depth":400,"text":372},{"id":858,"depth":400,"text":859},{"id":1326,"depth":400,"text":1327},"2020-12-09 08:05 +0100",null,"md","Using mitmproxy to debug java web calls",{},"\u002F2020\u002F12\u002F09\u002Fmitmproxy-with-java",{"title":206,"description":213},{"loc":1355},"2020\u002F12\u002F09\u002Fmitmproxy-with-java",[358,226,1360],"tutorial","Vowk69jBCpiM5yWZv-0Vw4h_-In-KDEUmw6R-iKiXsI",1775293005801]