├── .gitignore ├── Example ├── HTTPProxyURLProtocol.xcodeproj │ └── project.pbxproj ├── HTTPProxyURLProtocol │ ├── Base.lproj │ │ └── MainMenu.xib │ ├── HTTPProxyURLProtocol-Info.plist │ ├── HTTPProxyURLProtocol-Prefix.pch │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── LLAppDelegate.h │ ├── LLAppDelegate.m │ ├── en.lproj │ │ ├── Credits.rtf │ │ └── InfoPlist.strings │ └── main.m ├── HTTPProxyURLProtocolTests │ ├── HTTPProxyURLProtocolTests-Info.plist │ ├── HTTPProxyURLProtocolTests.m │ └── en.lproj │ │ └── InfoPlist.strings ├── Podfile └── Podfile.lock ├── LICENSE ├── LLHTTPProxyURLProtocol.podspec ├── LLHTTPProxyURLProtocol ├── LLHTTPProxyURLProtocol.h └── LLHTTPProxyURLProtocol.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # VIM temp files 2 | *.sw? 3 | 4 | # Python 5 | *.py[cod] 6 | 7 | # OS X Finder 8 | .DS_Store 9 | 10 | # Xcode 11 | build/* 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | *.xcworkspace 21 | !default.xcworkspace 22 | xcuserdata 23 | *.moved-aside 24 | 25 | # In-App Commit Tracking 26 | *-Commit.plist 27 | 28 | # Cocoapods 29 | Pods 30 | 31 | # Kaleidoscope temp files 32 | *.orig 33 | 34 | # Converage files 35 | Resources/Scripts/env.sh 36 | Reports/* 37 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | archiveVersion 6 | 1 7 | classes 8 | 9 | objectVersion 10 | 46 11 | objects 12 | 13 | 0848B220055C9D65E4F548A5 14 | 15 | buildActionMask 16 | 2147483647 17 | files 18 | 19 | inputPaths 20 | 21 | isa 22 | PBXShellScriptBuildPhase 23 | name 24 | Check Pods Manifest.lock 25 | outputPaths 26 | 27 | runOnlyForDeploymentPostprocessing 28 | 0 29 | shellPath 30 | /bin/sh 31 | shellScript 32 | diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null 33 | if [[ $? != 0 ]] ; then 34 | cat << EOM 35 | error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation. 36 | EOM 37 | exit 1 38 | fi 39 | 40 | showEnvVarsInLog 41 | 0 42 | 43 | 2821F29ACCBA16183A486DB3 44 | 45 | children 46 | 47 | E3364C521C417451EDAC377D 48 | C283A47678CE987F7CEF7E1D 49 | 50 | isa 51 | PBXGroup 52 | name 53 | Pods 54 | sourceTree 55 | <group> 56 | 57 | 3CD9FB2414921BC347BCF43A 58 | 59 | fileRef 60 | C10590BE4F114701B7CFC885 61 | isa 62 | PBXBuildFile 63 | 64 | 3F65FF1A198DD50100702B5A 65 | 66 | children 67 | 68 | 3F65FF5A198DD5A400702B5A 69 | 3F65FF2C198DD50100702B5A 70 | 3F65FF4A198DD50200702B5A 71 | 3F65FF25198DD50100702B5A 72 | 3F65FF24198DD50100702B5A 73 | 2821F29ACCBA16183A486DB3 74 | 75 | isa 76 | PBXGroup 77 | sourceTree 78 | <group> 79 | 80 | 3F65FF1B198DD50100702B5A 81 | 82 | attributes 83 | 84 | CLASSPREFIX 85 | LL 86 | LastUpgradeCheck 87 | 0510 88 | ORGANIZATIONNAME 89 | Jeremy Foo 90 | TargetAttributes 91 | 92 | 3F65FF43198DD50200702B5A 93 | 94 | TestTargetID 95 | 3F65FF22198DD50100702B5A 96 | 97 | 98 | 99 | buildConfigurationList 100 | 3F65FF1E198DD50100702B5A 101 | compatibilityVersion 102 | Xcode 3.2 103 | developmentRegion 104 | English 105 | hasScannedForEncodings 106 | 0 107 | isa 108 | PBXProject 109 | knownRegions 110 | 111 | en 112 | Base 113 | 114 | mainGroup 115 | 3F65FF1A198DD50100702B5A 116 | productRefGroup 117 | 3F65FF24198DD50100702B5A 118 | projectDirPath 119 | 120 | projectReferences 121 | 122 | projectRoot 123 | 124 | targets 125 | 126 | 3F65FF22198DD50100702B5A 127 | 3F65FF43198DD50200702B5A 128 | 129 | 130 | 3F65FF1E198DD50100702B5A 131 | 132 | buildConfigurations 133 | 134 | 3F65FF52198DD50200702B5A 135 | 3F65FF53198DD50200702B5A 136 | 137 | defaultConfigurationIsVisible 138 | 0 139 | defaultConfigurationName 140 | Release 141 | isa 142 | XCConfigurationList 143 | 144 | 3F65FF1F198DD50100702B5A 145 | 146 | buildActionMask 147 | 2147483647 148 | files 149 | 150 | 3F65FF5D198DD5D000702B5A 151 | 3F65FF3A198DD50100702B5A 152 | 3F65FF33198DD50100702B5A 153 | 154 | isa 155 | PBXSourcesBuildPhase 156 | runOnlyForDeploymentPostprocessing 157 | 0 158 | 159 | 3F65FF20198DD50100702B5A 160 | 161 | buildActionMask 162 | 2147483647 163 | files 164 | 165 | 3F65FF27198DD50100702B5A 166 | 3CD9FB2414921BC347BCF43A 167 | 168 | isa 169 | PBXFrameworksBuildPhase 170 | runOnlyForDeploymentPostprocessing 171 | 0 172 | 173 | 3F65FF21198DD50100702B5A 174 | 175 | buildActionMask 176 | 2147483647 177 | files 178 | 179 | 3F65FF31198DD50100702B5A 180 | 3F65FF3F198DD50200702B5A 181 | 3F65FF37198DD50100702B5A 182 | 3F65FF3D198DD50200702B5A 183 | 184 | isa 185 | PBXResourcesBuildPhase 186 | runOnlyForDeploymentPostprocessing 187 | 0 188 | 189 | 3F65FF22198DD50100702B5A 190 | 191 | buildConfigurationList 192 | 3F65FF54198DD50200702B5A 193 | buildPhases 194 | 195 | 0848B220055C9D65E4F548A5 196 | 3F65FF1F198DD50100702B5A 197 | 3F65FF20198DD50100702B5A 198 | 3F65FF21198DD50100702B5A 199 | A6ECCB03471B5DAA6BAFAE8D 200 | 201 | buildRules 202 | 203 | dependencies 204 | 205 | isa 206 | PBXNativeTarget 207 | name 208 | HTTPProxyURLProtocol 209 | productName 210 | HTTPProxyURLProtocol 211 | productReference 212 | 3F65FF23198DD50100702B5A 213 | productType 214 | com.apple.product-type.application 215 | 216 | 3F65FF23198DD50100702B5A 217 | 218 | explicitFileType 219 | wrapper.application 220 | includeInIndex 221 | 0 222 | isa 223 | PBXFileReference 224 | path 225 | HTTPProxyURLProtocol.app 226 | sourceTree 227 | BUILT_PRODUCTS_DIR 228 | 229 | 3F65FF24198DD50100702B5A 230 | 231 | children 232 | 233 | 3F65FF23198DD50100702B5A 234 | 3F65FF44198DD50200702B5A 235 | 236 | isa 237 | PBXGroup 238 | name 239 | Products 240 | sourceTree 241 | <group> 242 | 243 | 3F65FF25198DD50100702B5A 244 | 245 | children 246 | 247 | 3F65FF26198DD50100702B5A 248 | 3F65FF45198DD50200702B5A 249 | 3F65FF28198DD50100702B5A 250 | C10590BE4F114701B7CFC885 251 | 252 | isa 253 | PBXGroup 254 | name 255 | Frameworks 256 | sourceTree 257 | <group> 258 | 259 | 3F65FF26198DD50100702B5A 260 | 261 | isa 262 | PBXFileReference 263 | lastKnownFileType 264 | wrapper.framework 265 | name 266 | Cocoa.framework 267 | path 268 | System/Library/Frameworks/Cocoa.framework 269 | sourceTree 270 | SDKROOT 271 | 272 | 3F65FF27198DD50100702B5A 273 | 274 | fileRef 275 | 3F65FF26198DD50100702B5A 276 | isa 277 | PBXBuildFile 278 | 279 | 3F65FF28198DD50100702B5A 280 | 281 | children 282 | 283 | 3F65FF29198DD50100702B5A 284 | 3F65FF2A198DD50100702B5A 285 | 3F65FF2B198DD50100702B5A 286 | 287 | isa 288 | PBXGroup 289 | name 290 | Other Frameworks 291 | sourceTree 292 | <group> 293 | 294 | 3F65FF29198DD50100702B5A 295 | 296 | isa 297 | PBXFileReference 298 | lastKnownFileType 299 | wrapper.framework 300 | name 301 | AppKit.framework 302 | path 303 | System/Library/Frameworks/AppKit.framework 304 | sourceTree 305 | SDKROOT 306 | 307 | 3F65FF2A198DD50100702B5A 308 | 309 | isa 310 | PBXFileReference 311 | lastKnownFileType 312 | wrapper.framework 313 | name 314 | CoreData.framework 315 | path 316 | System/Library/Frameworks/CoreData.framework 317 | sourceTree 318 | SDKROOT 319 | 320 | 3F65FF2B198DD50100702B5A 321 | 322 | isa 323 | PBXFileReference 324 | lastKnownFileType 325 | wrapper.framework 326 | name 327 | Foundation.framework 328 | path 329 | System/Library/Frameworks/Foundation.framework 330 | sourceTree 331 | SDKROOT 332 | 333 | 3F65FF2C198DD50100702B5A 334 | 335 | children 336 | 337 | 3F65FF38198DD50100702B5A 338 | 3F65FF39198DD50100702B5A 339 | 3F65FF3B198DD50200702B5A 340 | 3F65FF3E198DD50200702B5A 341 | 3F65FF2D198DD50100702B5A 342 | 343 | isa 344 | PBXGroup 345 | path 346 | HTTPProxyURLProtocol 347 | sourceTree 348 | <group> 349 | 350 | 3F65FF2D198DD50100702B5A 351 | 352 | children 353 | 354 | 3F65FF2E198DD50100702B5A 355 | 3F65FF2F198DD50100702B5A 356 | 3F65FF32198DD50100702B5A 357 | 3F65FF34198DD50100702B5A 358 | 3F65FF35198DD50100702B5A 359 | 360 | isa 361 | PBXGroup 362 | name 363 | Supporting Files 364 | sourceTree 365 | <group> 366 | 367 | 3F65FF2E198DD50100702B5A 368 | 369 | isa 370 | PBXFileReference 371 | lastKnownFileType 372 | text.plist.xml 373 | path 374 | HTTPProxyURLProtocol-Info.plist 375 | sourceTree 376 | <group> 377 | 378 | 3F65FF2F198DD50100702B5A 379 | 380 | children 381 | 382 | 3F65FF30198DD50100702B5A 383 | 384 | isa 385 | PBXVariantGroup 386 | name 387 | InfoPlist.strings 388 | sourceTree 389 | <group> 390 | 391 | 3F65FF30198DD50100702B5A 392 | 393 | isa 394 | PBXFileReference 395 | lastKnownFileType 396 | text.plist.strings 397 | name 398 | en 399 | path 400 | en.lproj/InfoPlist.strings 401 | sourceTree 402 | <group> 403 | 404 | 3F65FF31198DD50100702B5A 405 | 406 | fileRef 407 | 3F65FF2F198DD50100702B5A 408 | isa 409 | PBXBuildFile 410 | 411 | 3F65FF32198DD50100702B5A 412 | 413 | isa 414 | PBXFileReference 415 | lastKnownFileType 416 | sourcecode.c.objc 417 | path 418 | main.m 419 | sourceTree 420 | <group> 421 | 422 | 3F65FF33198DD50100702B5A 423 | 424 | fileRef 425 | 3F65FF32198DD50100702B5A 426 | isa 427 | PBXBuildFile 428 | 429 | 3F65FF34198DD50100702B5A 430 | 431 | isa 432 | PBXFileReference 433 | lastKnownFileType 434 | sourcecode.c.h 435 | path 436 | HTTPProxyURLProtocol-Prefix.pch 437 | sourceTree 438 | <group> 439 | 440 | 3F65FF35198DD50100702B5A 441 | 442 | children 443 | 444 | 3F65FF36198DD50100702B5A 445 | 446 | isa 447 | PBXVariantGroup 448 | name 449 | Credits.rtf 450 | sourceTree 451 | <group> 452 | 453 | 3F65FF36198DD50100702B5A 454 | 455 | isa 456 | PBXFileReference 457 | lastKnownFileType 458 | text.rtf 459 | name 460 | en 461 | path 462 | en.lproj/Credits.rtf 463 | sourceTree 464 | <group> 465 | 466 | 3F65FF37198DD50100702B5A 467 | 468 | fileRef 469 | 3F65FF35198DD50100702B5A 470 | isa 471 | PBXBuildFile 472 | 473 | 3F65FF38198DD50100702B5A 474 | 475 | isa 476 | PBXFileReference 477 | lastKnownFileType 478 | sourcecode.c.h 479 | path 480 | LLAppDelegate.h 481 | sourceTree 482 | <group> 483 | 484 | 3F65FF39198DD50100702B5A 485 | 486 | isa 487 | PBXFileReference 488 | lastKnownFileType 489 | sourcecode.c.objc 490 | path 491 | LLAppDelegate.m 492 | sourceTree 493 | <group> 494 | 495 | 3F65FF3A198DD50100702B5A 496 | 497 | fileRef 498 | 3F65FF39198DD50100702B5A 499 | isa 500 | PBXBuildFile 501 | 502 | 3F65FF3B198DD50200702B5A 503 | 504 | children 505 | 506 | 3F65FF3C198DD50200702B5A 507 | 508 | isa 509 | PBXVariantGroup 510 | name 511 | MainMenu.xib 512 | sourceTree 513 | <group> 514 | 515 | 3F65FF3C198DD50200702B5A 516 | 517 | isa 518 | PBXFileReference 519 | lastKnownFileType 520 | file.xib 521 | name 522 | Base 523 | path 524 | Base.lproj/MainMenu.xib 525 | sourceTree 526 | <group> 527 | 528 | 3F65FF3D198DD50200702B5A 529 | 530 | fileRef 531 | 3F65FF3B198DD50200702B5A 532 | isa 533 | PBXBuildFile 534 | 535 | 3F65FF3E198DD50200702B5A 536 | 537 | isa 538 | PBXFileReference 539 | lastKnownFileType 540 | folder.assetcatalog 541 | path 542 | Images.xcassets 543 | sourceTree 544 | <group> 545 | 546 | 3F65FF3F198DD50200702B5A 547 | 548 | fileRef 549 | 3F65FF3E198DD50200702B5A 550 | isa 551 | PBXBuildFile 552 | 553 | 3F65FF40198DD50200702B5A 554 | 555 | buildActionMask 556 | 2147483647 557 | files 558 | 559 | 3F65FF51198DD50200702B5A 560 | 561 | isa 562 | PBXSourcesBuildPhase 563 | runOnlyForDeploymentPostprocessing 564 | 0 565 | 566 | 3F65FF41198DD50200702B5A 567 | 568 | buildActionMask 569 | 2147483647 570 | files 571 | 572 | 3F65FF47198DD50200702B5A 573 | 3F65FF46198DD50200702B5A 574 | 575 | isa 576 | PBXFrameworksBuildPhase 577 | runOnlyForDeploymentPostprocessing 578 | 0 579 | 580 | 3F65FF42198DD50200702B5A 581 | 582 | buildActionMask 583 | 2147483647 584 | files 585 | 586 | 3F65FF4F198DD50200702B5A 587 | 588 | isa 589 | PBXResourcesBuildPhase 590 | runOnlyForDeploymentPostprocessing 591 | 0 592 | 593 | 3F65FF43198DD50200702B5A 594 | 595 | buildConfigurationList 596 | 3F65FF57198DD50200702B5A 597 | buildPhases 598 | 599 | 3F65FF40198DD50200702B5A 600 | 3F65FF41198DD50200702B5A 601 | 3F65FF42198DD50200702B5A 602 | 603 | buildRules 604 | 605 | dependencies 606 | 607 | 3F65FF49198DD50200702B5A 608 | 609 | isa 610 | PBXNativeTarget 611 | name 612 | HTTPProxyURLProtocolTests 613 | productName 614 | HTTPProxyURLProtocolTests 615 | productReference 616 | 3F65FF44198DD50200702B5A 617 | productType 618 | com.apple.product-type.bundle.unit-test 619 | 620 | 3F65FF44198DD50200702B5A 621 | 622 | explicitFileType 623 | wrapper.cfbundle 624 | includeInIndex 625 | 0 626 | isa 627 | PBXFileReference 628 | path 629 | HTTPProxyURLProtocolTests.xctest 630 | sourceTree 631 | BUILT_PRODUCTS_DIR 632 | 633 | 3F65FF45198DD50200702B5A 634 | 635 | isa 636 | PBXFileReference 637 | lastKnownFileType 638 | wrapper.framework 639 | name 640 | XCTest.framework 641 | path 642 | Library/Frameworks/XCTest.framework 643 | sourceTree 644 | DEVELOPER_DIR 645 | 646 | 3F65FF46198DD50200702B5A 647 | 648 | fileRef 649 | 3F65FF45198DD50200702B5A 650 | isa 651 | PBXBuildFile 652 | 653 | 3F65FF47198DD50200702B5A 654 | 655 | fileRef 656 | 3F65FF26198DD50100702B5A 657 | isa 658 | PBXBuildFile 659 | 660 | 3F65FF48198DD50200702B5A 661 | 662 | containerPortal 663 | 3F65FF1B198DD50100702B5A 664 | isa 665 | PBXContainerItemProxy 666 | proxyType 667 | 1 668 | remoteGlobalIDString 669 | 3F65FF22198DD50100702B5A 670 | remoteInfo 671 | HTTPProxyURLProtocol 672 | 673 | 3F65FF49198DD50200702B5A 674 | 675 | isa 676 | PBXTargetDependency 677 | target 678 | 3F65FF22198DD50100702B5A 679 | targetProxy 680 | 3F65FF48198DD50200702B5A 681 | 682 | 3F65FF4A198DD50200702B5A 683 | 684 | children 685 | 686 | 3F65FF50198DD50200702B5A 687 | 3F65FF4B198DD50200702B5A 688 | 689 | isa 690 | PBXGroup 691 | path 692 | HTTPProxyURLProtocolTests 693 | sourceTree 694 | <group> 695 | 696 | 3F65FF4B198DD50200702B5A 697 | 698 | children 699 | 700 | 3F65FF4C198DD50200702B5A 701 | 3F65FF4D198DD50200702B5A 702 | 703 | isa 704 | PBXGroup 705 | name 706 | Supporting Files 707 | sourceTree 708 | <group> 709 | 710 | 3F65FF4C198DD50200702B5A 711 | 712 | isa 713 | PBXFileReference 714 | lastKnownFileType 715 | text.plist.xml 716 | path 717 | HTTPProxyURLProtocolTests-Info.plist 718 | sourceTree 719 | <group> 720 | 721 | 3F65FF4D198DD50200702B5A 722 | 723 | children 724 | 725 | 3F65FF4E198DD50200702B5A 726 | 727 | isa 728 | PBXVariantGroup 729 | name 730 | InfoPlist.strings 731 | sourceTree 732 | <group> 733 | 734 | 3F65FF4E198DD50200702B5A 735 | 736 | isa 737 | PBXFileReference 738 | lastKnownFileType 739 | text.plist.strings 740 | name 741 | en 742 | path 743 | en.lproj/InfoPlist.strings 744 | sourceTree 745 | <group> 746 | 747 | 3F65FF4F198DD50200702B5A 748 | 749 | fileRef 750 | 3F65FF4D198DD50200702B5A 751 | isa 752 | PBXBuildFile 753 | 754 | 3F65FF50198DD50200702B5A 755 | 756 | isa 757 | PBXFileReference 758 | lastKnownFileType 759 | sourcecode.c.objc 760 | path 761 | HTTPProxyURLProtocolTests.m 762 | sourceTree 763 | <group> 764 | 765 | 3F65FF51198DD50200702B5A 766 | 767 | fileRef 768 | 3F65FF50198DD50200702B5A 769 | isa 770 | PBXBuildFile 771 | 772 | 3F65FF52198DD50200702B5A 773 | 774 | buildSettings 775 | 776 | ALWAYS_SEARCH_USER_PATHS 777 | NO 778 | CLANG_CXX_LANGUAGE_STANDARD 779 | gnu++0x 780 | CLANG_CXX_LIBRARY 781 | libc++ 782 | CLANG_ENABLE_MODULES 783 | YES 784 | CLANG_ENABLE_OBJC_ARC 785 | YES 786 | CLANG_WARN_BOOL_CONVERSION 787 | YES 788 | CLANG_WARN_CONSTANT_CONVERSION 789 | YES 790 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE 791 | YES_ERROR 792 | CLANG_WARN_EMPTY_BODY 793 | YES 794 | CLANG_WARN_ENUM_CONVERSION 795 | YES 796 | CLANG_WARN_INT_CONVERSION 797 | YES 798 | CLANG_WARN_OBJC_ROOT_CLASS 799 | YES_ERROR 800 | CLANG_WARN__DUPLICATE_METHOD_MATCH 801 | YES 802 | COPY_PHASE_STRIP 803 | NO 804 | GCC_C_LANGUAGE_STANDARD 805 | gnu99 806 | GCC_DYNAMIC_NO_PIC 807 | NO 808 | GCC_ENABLE_OBJC_EXCEPTIONS 809 | YES 810 | GCC_OPTIMIZATION_LEVEL 811 | 0 812 | GCC_PREPROCESSOR_DEFINITIONS 813 | 814 | DEBUG=1 815 | $(inherited) 816 | 817 | GCC_SYMBOLS_PRIVATE_EXTERN 818 | NO 819 | GCC_WARN_64_TO_32_BIT_CONVERSION 820 | YES 821 | GCC_WARN_ABOUT_RETURN_TYPE 822 | YES_ERROR 823 | GCC_WARN_UNDECLARED_SELECTOR 824 | YES 825 | GCC_WARN_UNINITIALIZED_AUTOS 826 | YES_AGGRESSIVE 827 | GCC_WARN_UNUSED_FUNCTION 828 | YES 829 | GCC_WARN_UNUSED_VARIABLE 830 | YES 831 | MACOSX_DEPLOYMENT_TARGET 832 | 10.9 833 | ONLY_ACTIVE_ARCH 834 | YES 835 | SDKROOT 836 | macosx 837 | 838 | isa 839 | XCBuildConfiguration 840 | name 841 | Debug 842 | 843 | 3F65FF53198DD50200702B5A 844 | 845 | buildSettings 846 | 847 | ALWAYS_SEARCH_USER_PATHS 848 | NO 849 | CLANG_CXX_LANGUAGE_STANDARD 850 | gnu++0x 851 | CLANG_CXX_LIBRARY 852 | libc++ 853 | CLANG_ENABLE_MODULES 854 | YES 855 | CLANG_ENABLE_OBJC_ARC 856 | YES 857 | CLANG_WARN_BOOL_CONVERSION 858 | YES 859 | CLANG_WARN_CONSTANT_CONVERSION 860 | YES 861 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE 862 | YES_ERROR 863 | CLANG_WARN_EMPTY_BODY 864 | YES 865 | CLANG_WARN_ENUM_CONVERSION 866 | YES 867 | CLANG_WARN_INT_CONVERSION 868 | YES 869 | CLANG_WARN_OBJC_ROOT_CLASS 870 | YES_ERROR 871 | CLANG_WARN__DUPLICATE_METHOD_MATCH 872 | YES 873 | COPY_PHASE_STRIP 874 | YES 875 | DEBUG_INFORMATION_FORMAT 876 | dwarf-with-dsym 877 | ENABLE_NS_ASSERTIONS 878 | NO 879 | GCC_C_LANGUAGE_STANDARD 880 | gnu99 881 | GCC_ENABLE_OBJC_EXCEPTIONS 882 | YES 883 | GCC_WARN_64_TO_32_BIT_CONVERSION 884 | YES 885 | GCC_WARN_ABOUT_RETURN_TYPE 886 | YES_ERROR 887 | GCC_WARN_UNDECLARED_SELECTOR 888 | YES 889 | GCC_WARN_UNINITIALIZED_AUTOS 890 | YES_AGGRESSIVE 891 | GCC_WARN_UNUSED_FUNCTION 892 | YES 893 | GCC_WARN_UNUSED_VARIABLE 894 | YES 895 | MACOSX_DEPLOYMENT_TARGET 896 | 10.9 897 | SDKROOT 898 | macosx 899 | 900 | isa 901 | XCBuildConfiguration 902 | name 903 | Release 904 | 905 | 3F65FF54198DD50200702B5A 906 | 907 | buildConfigurations 908 | 909 | 3F65FF55198DD50200702B5A 910 | 3F65FF56198DD50200702B5A 911 | 912 | defaultConfigurationIsVisible 913 | 0 914 | defaultConfigurationName 915 | Release 916 | isa 917 | XCConfigurationList 918 | 919 | 3F65FF55198DD50200702B5A 920 | 921 | baseConfigurationReference 922 | E3364C521C417451EDAC377D 923 | buildSettings 924 | 925 | ASSETCATALOG_COMPILER_APPICON_NAME 926 | AppIcon 927 | COMBINE_HIDPI_IMAGES 928 | YES 929 | GCC_PRECOMPILE_PREFIX_HEADER 930 | YES 931 | GCC_PREFIX_HEADER 932 | HTTPProxyURLProtocol/HTTPProxyURLProtocol-Prefix.pch 933 | INFOPLIST_FILE 934 | HTTPProxyURLProtocol/HTTPProxyURLProtocol-Info.plist 935 | PRODUCT_NAME 936 | $(TARGET_NAME) 937 | WRAPPER_EXTENSION 938 | app 939 | 940 | isa 941 | XCBuildConfiguration 942 | name 943 | Debug 944 | 945 | 3F65FF56198DD50200702B5A 946 | 947 | baseConfigurationReference 948 | C283A47678CE987F7CEF7E1D 949 | buildSettings 950 | 951 | ASSETCATALOG_COMPILER_APPICON_NAME 952 | AppIcon 953 | COMBINE_HIDPI_IMAGES 954 | YES 955 | GCC_PRECOMPILE_PREFIX_HEADER 956 | YES 957 | GCC_PREFIX_HEADER 958 | HTTPProxyURLProtocol/HTTPProxyURLProtocol-Prefix.pch 959 | INFOPLIST_FILE 960 | HTTPProxyURLProtocol/HTTPProxyURLProtocol-Info.plist 961 | PRODUCT_NAME 962 | $(TARGET_NAME) 963 | WRAPPER_EXTENSION 964 | app 965 | 966 | isa 967 | XCBuildConfiguration 968 | name 969 | Release 970 | 971 | 3F65FF57198DD50200702B5A 972 | 973 | buildConfigurations 974 | 975 | 3F65FF58198DD50200702B5A 976 | 3F65FF59198DD50200702B5A 977 | 978 | defaultConfigurationIsVisible 979 | 0 980 | defaultConfigurationName 981 | Release 982 | isa 983 | XCConfigurationList 984 | 985 | 3F65FF58198DD50200702B5A 986 | 987 | buildSettings 988 | 989 | BUNDLE_LOADER 990 | $(BUILT_PRODUCTS_DIR)/HTTPProxyURLProtocol.app/Contents/MacOS/HTTPProxyURLProtocol 991 | COMBINE_HIDPI_IMAGES 992 | YES 993 | FRAMEWORK_SEARCH_PATHS 994 | 995 | $(DEVELOPER_FRAMEWORKS_DIR) 996 | $(inherited) 997 | 998 | GCC_PRECOMPILE_PREFIX_HEADER 999 | YES 1000 | GCC_PREFIX_HEADER 1001 | HTTPProxyURLProtocol/HTTPProxyURLProtocol-Prefix.pch 1002 | GCC_PREPROCESSOR_DEFINITIONS 1003 | 1004 | DEBUG=1 1005 | $(inherited) 1006 | 1007 | INFOPLIST_FILE 1008 | HTTPProxyURLProtocolTests/HTTPProxyURLProtocolTests-Info.plist 1009 | PRODUCT_NAME 1010 | $(TARGET_NAME) 1011 | TEST_HOST 1012 | $(BUNDLE_LOADER) 1013 | WRAPPER_EXTENSION 1014 | xctest 1015 | 1016 | isa 1017 | XCBuildConfiguration 1018 | name 1019 | Debug 1020 | 1021 | 3F65FF59198DD50200702B5A 1022 | 1023 | buildSettings 1024 | 1025 | BUNDLE_LOADER 1026 | $(BUILT_PRODUCTS_DIR)/HTTPProxyURLProtocol.app/Contents/MacOS/HTTPProxyURLProtocol 1027 | COMBINE_HIDPI_IMAGES 1028 | YES 1029 | FRAMEWORK_SEARCH_PATHS 1030 | 1031 | $(DEVELOPER_FRAMEWORKS_DIR) 1032 | $(inherited) 1033 | 1034 | GCC_PRECOMPILE_PREFIX_HEADER 1035 | YES 1036 | GCC_PREFIX_HEADER 1037 | HTTPProxyURLProtocol/HTTPProxyURLProtocol-Prefix.pch 1038 | INFOPLIST_FILE 1039 | HTTPProxyURLProtocolTests/HTTPProxyURLProtocolTests-Info.plist 1040 | PRODUCT_NAME 1041 | $(TARGET_NAME) 1042 | TEST_HOST 1043 | $(BUNDLE_LOADER) 1044 | WRAPPER_EXTENSION 1045 | xctest 1046 | 1047 | isa 1048 | XCBuildConfiguration 1049 | name 1050 | Release 1051 | 1052 | 3F65FF5A198DD5A400702B5A 1053 | 1054 | children 1055 | 1056 | 3F65FF5B198DD5D000702B5A 1057 | 3F65FF5C198DD5D000702B5A 1058 | 1059 | isa 1060 | PBXGroup 1061 | name 1062 | NSURLProtocol 1063 | path 1064 | ../LLHTTPProxyURLProtocol 1065 | sourceTree 1066 | <group> 1067 | 1068 | 3F65FF5B198DD5D000702B5A 1069 | 1070 | fileEncoding 1071 | 4 1072 | isa 1073 | PBXFileReference 1074 | lastKnownFileType 1075 | sourcecode.c.h 1076 | path 1077 | LLHTTPProxyURLProtocol.h 1078 | sourceTree 1079 | <group> 1080 | 1081 | 3F65FF5C198DD5D000702B5A 1082 | 1083 | fileEncoding 1084 | 4 1085 | isa 1086 | PBXFileReference 1087 | lastKnownFileType 1088 | sourcecode.c.objc 1089 | path 1090 | LLHTTPProxyURLProtocol.m 1091 | sourceTree 1092 | <group> 1093 | 1094 | 3F65FF5D198DD5D000702B5A 1095 | 1096 | fileRef 1097 | 3F65FF5C198DD5D000702B5A 1098 | isa 1099 | PBXBuildFile 1100 | 1101 | A6ECCB03471B5DAA6BAFAE8D 1102 | 1103 | buildActionMask 1104 | 2147483647 1105 | files 1106 | 1107 | inputPaths 1108 | 1109 | isa 1110 | PBXShellScriptBuildPhase 1111 | name 1112 | Copy Pods Resources 1113 | outputPaths 1114 | 1115 | runOnlyForDeploymentPostprocessing 1116 | 0 1117 | shellPath 1118 | /bin/sh 1119 | shellScript 1120 | "${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh" 1121 | 1122 | showEnvVarsInLog 1123 | 0 1124 | 1125 | C10590BE4F114701B7CFC885 1126 | 1127 | explicitFileType 1128 | archive.ar 1129 | includeInIndex 1130 | 0 1131 | isa 1132 | PBXFileReference 1133 | path 1134 | libPods.a 1135 | sourceTree 1136 | BUILT_PRODUCTS_DIR 1137 | 1138 | C283A47678CE987F7CEF7E1D 1139 | 1140 | includeInIndex 1141 | 1 1142 | isa 1143 | PBXFileReference 1144 | lastKnownFileType 1145 | text.xcconfig 1146 | name 1147 | Pods.release.xcconfig 1148 | path 1149 | Pods/Target Support Files/Pods/Pods.release.xcconfig 1150 | sourceTree 1151 | <group> 1152 | 1153 | E3364C521C417451EDAC377D 1154 | 1155 | includeInIndex 1156 | 1 1157 | isa 1158 | PBXFileReference 1159 | lastKnownFileType 1160 | text.xcconfig 1161 | name 1162 | Pods.debug.xcconfig 1163 | path 1164 | Pods/Target Support Files/Pods/Pods.debug.xcconfig 1165 | sourceTree 1166 | <group> 1167 | 1168 | 1169 | rootObject 1170 | 3F65FF1B198DD50100702B5A 1171 | 1172 | 1173 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 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 | 67 | 68 | 69 | 70 | 71 | 72 | 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 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | Default 539 | 540 | 541 | 542 | 543 | 544 | 545 | Left to Right 546 | 547 | 548 | 549 | 550 | 551 | 552 | Right to Left 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | Default 564 | 565 | 566 | 567 | 568 | 569 | 570 | Left to Right 571 | 572 | 573 | 574 | 575 | 576 | 577 | Right to Left 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/HTTPProxyURLProtocol-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | co.lazylabs.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2014 Jeremy Foo. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/HTTPProxyURLProtocol-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/LLAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LLAppDelegate.h 3 | // HTTPProxyURLProtocol 4 | // 5 | // Created by Jeremy Foo on 2/8/14. 6 | // Copyright (c) 2014 Jeremy Foo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LLAppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/LLAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // LLAppDelegate.m 3 | // HTTPProxyURLProtocol 4 | // 5 | // Created by Jeremy Foo on 2/8/14. 6 | // Copyright (c) 2014 Jeremy Foo. All rights reserved. 7 | // 8 | 9 | #import "LLAppDelegate.h" 10 | #import 11 | #import "LLHTTPProxyURLProtocol.h" 12 | 13 | @implementation LLAppDelegate 14 | 15 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 16 | { 17 | // Insert code here to initialize your application 18 | [NSURLProtocol registerClass:[LLHTTPProxyURLProtocol class]]; 19 | 20 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://whatismyipaddress.com"] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0f]; 21 | request.validatesCertificateChain = NO; 22 | request.proxyServerURL = [NSURL URLWithString:@"http://user:password@proxy.server:port"]; 23 | request.HTTPMethod = @"GET"; 24 | 25 | AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 26 | [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 27 | NSLog(@"Succes: (%@) -> %@", operation.response.allHeaderFields, [[NSString alloc] initWithData:responseObject encoding:NSASCIIStringEncoding]); 28 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 29 | NSLog(@"Failure: %@", error); 30 | }]; 31 | 32 | [requestOperation start]; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocol/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HTTPProxyURLProtocol 4 | // 5 | // Created by Jeremy Foo on 2/8/14. 6 | // Copyright (c) 2014 Jeremy Foo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) 12 | { 13 | return NSApplicationMain(argc, argv); 14 | } 15 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocolTests/HTTPProxyURLProtocolTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | co.lazylabs.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocolTests/HTTPProxyURLProtocolTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // HTTPProxyURLProtocolTests.m 3 | // HTTPProxyURLProtocolTests 4 | // 5 | // Created by Jeremy Foo on 2/8/14. 6 | // Copyright (c) 2014 Jeremy Foo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HTTPProxyURLProtocolTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation HTTPProxyURLProtocolTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Example/HTTPProxyURLProtocolTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.9' 2 | source 'https://github.com/CocoaPods/Specs.git' 3 | 4 | inhibit_all_warnings! 5 | pod 'AFNetworking' 6 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - AFNetworking (2.5.0): 3 | - AFNetworking/NSURLConnection (= 2.5.0) 4 | - AFNetworking/NSURLSession (= 2.5.0) 5 | - AFNetworking/Reachability (= 2.5.0) 6 | - AFNetworking/Security (= 2.5.0) 7 | - AFNetworking/Serialization (= 2.5.0) 8 | - AFNetworking/UIKit (= 2.5.0) 9 | - AFNetworking/NSURLConnection (2.5.0): 10 | - AFNetworking/Reachability 11 | - AFNetworking/Security 12 | - AFNetworking/Serialization 13 | - AFNetworking/NSURLSession (2.5.0): 14 | - AFNetworking/Reachability 15 | - AFNetworking/Security 16 | - AFNetworking/Serialization 17 | - AFNetworking/Reachability (2.5.0) 18 | - AFNetworking/Security (2.5.0) 19 | - AFNetworking/Serialization (2.5.0) 20 | 21 | DEPENDENCIES: 22 | - AFNetworking 23 | 24 | SPEC CHECKSUMS: 25 | AFNetworking: 0f54cb5d16ce38c1b76948faffb8d5fb705021c7 26 | 27 | COCOAPODS: 0.35.0 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Jeremy Foo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LLHTTPProxyURLProtocol.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "LLHTTPProxyURLProtocol" 4 | s.version = "0.0.1" 5 | s.summary = "NSURLProtocol that lets you send NSURLRequests over a HTTP/HTTPS/SOCKS proxy server" 6 | 7 | s.description = <<-DESC 8 | NSURLConnection is great but it doesn't allow you to send requests over a proxy server. 9 | LLHTTPProxyURLProtocol is designed to be a transparent layer for NSURLConnection such 10 | that you can specify a proxy server along with credentials and push the request through 11 | that proxy server. 12 | 13 | It uses the lower level CFReadStreamRef APIs to achieve this magic. 14 | 15 | Tested to support 16 | * HTTP Proxies (with authentication) 17 | 18 | Theoratically supports 19 | * Socks Proxies (with authentication) 20 | * HTTPS Proxies 21 | DESC 22 | 23 | s.homepage = "http://github.com/echoz/LLHTTPProxyURLProtocol" 24 | 25 | s.license = { :type => "MIT" } 26 | s.author = { "Jeremy Foo" => "jeremy@lazylabs.co" } 27 | 28 | s.ios.deployment_target = "5.0" 29 | s.osx.deployment_target = "10.7" 30 | 31 | s.source = { :git => "https://github.com/echoz/LLHTTPProxyURLProtocol.git", :tag => "0.0.1" } 32 | 33 | s.source_files = "LLHTTPProxyURLProtocol/*.{h,m}" 34 | 35 | s.requires_arc = true 36 | 37 | end 38 | -------------------------------------------------------------------------------- /LLHTTPProxyURLProtocol/LLHTTPProxyURLProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // LLHTTPProxyURLProtocol.h 3 | // HTTPProxyURLProtocol 4 | // 5 | // Created by Jeremy Foo on 2/8/14. 6 | // Copyright (c) 2014 Jeremy Foo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString *const LLHTTPProxyURLProtocolProxyServerKey; 12 | 13 | // Supports socks proxies by using socks scheme 14 | // socks4://user:pass@server:port 15 | // socks5://user:pass@server:port 16 | // http://user:pass@server:port 17 | // https://user:pass@server:port 18 | 19 | @interface LLHTTPProxyURLProtocol : NSURLProtocol 20 | @property (nonatomic, strong, readonly) NSInputStream *HTTPResponseStream; 21 | @property (nonatomic, strong, readonly) NSHTTPURLResponse *HTTPURLResponse; 22 | @property (nonatomic, assign, readonly) CFHTTPMessageRef responseMessage; 23 | @property (nonatomic, assign, readonly) CFHTTPMessageRef requestMessage; 24 | @end 25 | 26 | @interface NSURLRequest (LLHTTPProxyURLProtocol) 27 | @property (nonatomic, readonly) BOOL validatesCertificateChain; 28 | @property (nonatomic, readonly) NSArray *certificateChain; 29 | @property (nonatomic, readonly) NSURL *proxyServerURL; 30 | @end 31 | 32 | @interface NSMutableURLRequest (LLHTTPProxyURLProtocol) 33 | @property (nonatomic, assign) BOOL validatesCertificateChain; 34 | @property (nonatomic, copy) NSArray *certificateChain; 35 | @property (nonatomic, copy) NSURL *proxyServerURL; 36 | @end -------------------------------------------------------------------------------- /LLHTTPProxyURLProtocol/LLHTTPProxyURLProtocol.m: -------------------------------------------------------------------------------- 1 | // 2 | // LLHTTPProxyURLProtocol.m 3 | // HTTPProxyURLProtocol 4 | // 5 | // Created by Jeremy Foo on 2/8/14. 6 | // Copyright (c) 2014 Jeremy Foo. All rights reserved. 7 | // 8 | 9 | #import "LLHTTPProxyURLProtocol.h" 10 | 11 | #define HTTP_HEADER_MAX_LENGTH 16384 12 | NSString *const LLHTTPProxyURLProtocolProxyServerKey = @"co.lazylabs.LLHTTPProxyURLProtocol.proxy.address"; 13 | 14 | @interface LLHTTPProxyURLProtocol () 15 | @property (nonatomic, assign) NSUInteger authFailureCount; 16 | @property (nonatomic, strong) NSURLAuthenticationChallenge *authChallenge; 17 | @property (nonatomic, strong) NSURLCredential *internalHTTPProxyCredential; 18 | @end 19 | 20 | @implementation LLHTTPProxyURLProtocol 21 | @synthesize HTTPResponseStream = _HTTPResponseStream; 22 | @synthesize requestMessage = _requestMessage; 23 | 24 | +(BOOL)canInitWithRequest:(NSURLRequest *)request { 25 | if (![request.URL.scheme hasPrefix:@"http"]) return NO; 26 | return ([[NSURLProtocol propertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:request] isKindOfClass:[NSURL class]]); 27 | } 28 | +(NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } 29 | 30 | #pragma mark - Object Life Cycle 31 | 32 | -(id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id)client { 33 | if ((self = [super initWithRequest:request cachedResponse:cachedResponse client:client])) { 34 | _authFailureCount = 0; 35 | 36 | if ([request.proxyServerURL.scheme hasPrefix:@"http"]) 37 | self.internalHTTPProxyCredential = [NSURLCredential credentialWithUser:request.proxyServerURL.user password:request.proxyServerURL.password persistence:NSURLCredentialPersistenceNone]; 38 | 39 | } 40 | return self; 41 | } 42 | 43 | -(void)dealloc { 44 | [self stopLoading]; 45 | if (_responseMessage) CFRelease(_responseMessage), _responseMessage = NULL; 46 | if (_requestMessage) CFRelease(_requestMessage), _requestMessage = NULL; 47 | } 48 | 49 | #pragma mark - Properties 50 | 51 | -(CFHTTPMessageRef)requestMessage { 52 | if (_requestMessage == NULL) { 53 | CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, (CFStringRef)[self.request.URL absoluteString], NULL); 54 | _requestMessage = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (__bridge CFStringRef)self.request.HTTPMethod, url, kCFHTTPVersion1_1); 55 | 56 | // build headers 57 | for (NSString *header in [self.request allHTTPHeaderFields]) 58 | CFHTTPMessageSetHeaderFieldValue(self.requestMessage, (__bridge CFStringRef)header, (__bridge CFStringRef)([[self.request allHTTPHeaderFields] objectForKey:header])); 59 | } 60 | return _requestMessage; 61 | } 62 | 63 | -(NSInputStream *)HTTPResponseStream { 64 | if (!_HTTPResponseStream) { 65 | // create read stream for CFHTTPStream 66 | CFReadStreamRef requestReadStream = NULL; 67 | 68 | if (self.request.HTTPBodyStream) { 69 | requestReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, self.requestMessage, (__bridge CFReadStreamRef)(self.request.HTTPBodyStream)); 70 | } else { 71 | NSData *body = ([self.request.HTTPBody length] == 0) ? [NSData data] : self.request.HTTPBody; 72 | CFHTTPMessageSetBody(self.requestMessage, (__bridge CFDataRef)body); 73 | requestReadStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, self.requestMessage); 74 | } 75 | 76 | CFReadStreamSetProperty(requestReadStream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanFalse); 77 | 78 | // proxy settings 79 | NSAssert1([[NSURLProtocol propertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self.request] isKindOfClass:[NSURL class]], @"Proxy server specified must be in the form of an NSURL: %@", [NSURLProtocol propertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self.request]); 80 | NSURL *proxyURL = [NSURLProtocol propertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self.request]; 81 | NSAssert1([proxyURL.scheme hasPrefix:@"socks"] || [proxyURL.scheme hasPrefix:@"http"], @"Proxy Servers supported only include socks, https and http: %@", proxyURL.scheme); 82 | 83 | NSDictionary *proxySettings = nil; 84 | if ([proxyURL.scheme hasPrefix:@"socks"]) { 85 | NSAssert1([proxyURL.scheme hasPrefix:@"socks5"] || [proxyURL.scheme hasPrefix:@"socks4"], @"Only SOCKS5 and SOCKS4 proxy servers are supported: %@", proxyURL.scheme); 86 | 87 | NSMutableDictionary *socksSettings = [NSMutableDictionary dictionaryWithDictionary:@{(NSString *)kCFStreamPropertySOCKSProxyHost: proxyURL.host, (NSString *)kCFStreamPropertySOCKSProxyPort: proxyURL.port}]; 88 | if (proxyURL.user) [socksSettings setObject:proxyURL.user forKey:(NSString *)kCFStreamPropertySOCKSUser]; 89 | if (proxyURL.password) [socksSettings setObject:proxyURL.password forKey:(NSString *)kCFStreamPropertySOCKSPassword]; 90 | [socksSettings setObject:([proxyURL.scheme hasPrefix:@"socks5"]) ? (NSString *)kCFStreamSocketSOCKSVersion5 : (NSString *)kCFStreamSocketSOCKSVersion4 91 | forKey:(NSString *)kCFStreamPropertySOCKSVersion]; 92 | 93 | proxySettings = socksSettings; 94 | } else if ([proxyURL.scheme hasPrefix:@"https"]) { 95 | proxySettings = @{(NSString *)kCFStreamPropertyHTTPSProxyHost: proxyURL.host, (NSString *)kCFStreamPropertyHTTPSProxyPort: proxyURL.port}; 96 | } else { 97 | proxySettings = @{(NSString *)kCFStreamPropertyHTTPProxyHost: proxyURL.host, (NSString *)kCFStreamPropertyHTTPProxyPort: proxyURL.port}; 98 | } 99 | 100 | if (proxySettings) CFReadStreamSetProperty(requestReadStream, kCFStreamPropertyHTTPProxy, (__bridge CFTypeRef)(proxySettings)); 101 | 102 | // set pipelining support 103 | CFReadStreamSetProperty(requestReadStream, kCFStreamPropertyHTTPAttemptPersistentConnection, (__bridge CFTypeRef)(@(self.request.HTTPShouldUsePipelining))); 104 | 105 | // set cellular access 106 | CFReadStreamSetProperty(requestReadStream, kCFStreamPropertyNoCellular, (__bridge CFTypeRef)(@(!self.request.allowsCellularAccess))); 107 | 108 | // set SSL preferences 109 | CFReadStreamSetProperty(requestReadStream, kCFStreamSSLValidatesCertificateChain, (__bridge CFTypeRef)@(self.request.validatesCertificateChain)); 110 | if (self.request.certificateChain) CFReadStreamSetProperty(requestReadStream, kCFStreamSSLCertificates, (__bridge CFArrayRef)(self.request.certificateChain)); 111 | 112 | // service type 113 | 114 | if (self.request.networkServiceType == NSURLNetworkServiceTypeVoIP) CFReadStreamSetProperty(requestReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); 115 | if (self.request.networkServiceType == NSURLNetworkServiceTypeVideo) CFReadStreamSetProperty(requestReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVideo); 116 | if (self.request.networkServiceType == NSURLNetworkServiceTypeVoice) CFReadStreamSetProperty(requestReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoice); 117 | if (self.request.networkServiceType == NSURLNetworkServiceTypeBackground) CFReadStreamSetProperty(requestReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeBackground); 118 | 119 | _HTTPResponseStream = (__bridge NSInputStream *)(requestReadStream); 120 | } 121 | return _HTTPResponseStream; 122 | } 123 | 124 | #pragma mark - Networking Event 125 | 126 | -(void)startLoading { 127 | [self stopLoading]; 128 | 129 | self.authChallenge = nil; 130 | if (_responseMessage) CFRelease(_responseMessage), _responseMessage = NULL; 131 | _HTTPURLResponse = nil; 132 | 133 | self.HTTPResponseStream.delegate = self; 134 | [self.HTTPResponseStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 135 | [self.HTTPResponseStream open]; 136 | } 137 | 138 | -(void)stopLoading { 139 | if (!_HTTPResponseStream) return; 140 | 141 | self.HTTPResponseStream.delegate = nil; 142 | [self.HTTPResponseStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 143 | [self.HTTPResponseStream close], _HTTPResponseStream = nil; 144 | } 145 | 146 | #pragma mark - Authentication Delegate 147 | 148 | -(void)_restartLoadingWithCredential:(NSURLCredential *)credential { 149 | CFHTTPMessageAddAuthentication(self.requestMessage, self.responseMessage, (__bridge CFStringRef)(credential.user), (__bridge CFStringRef)(credential.password), NULL, YES); 150 | [self startLoading]; 151 | } 152 | 153 | - (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 154 | if (self.authChallenge != challenge) return; 155 | [self _restartLoadingWithCredential:credential]; 156 | } 157 | 158 | - (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 159 | _HTTPResponseStream = nil; 160 | [self startLoading]; 161 | } 162 | 163 | - (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 164 | // return auth error 165 | [self stopLoading]; 166 | [self.client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorUserCancelledAuthentication userInfo:nil]]; 167 | } 168 | 169 | -(void)performDefaultHandlingForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 170 | [self stopLoading]; 171 | [self.client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:kCFURLErrorUserAuthenticationRequired userInfo:nil]]; 172 | } 173 | 174 | #pragma mark - Stream Handling 175 | 176 | // https://github.com/graetzer/SGURLProtocol 177 | - (NSURLCacheStoragePolicy)cachePolicyForRequest:(NSURLRequest *)request response:(NSHTTPURLResponse *)response { 178 | BOOL cacheable = NO; 179 | NSURLCacheStoragePolicy result = NSURLCacheStorageNotAllowed; 180 | 181 | switch (response.statusCode) { 182 | case 200: 183 | case 203: 184 | case 206: 185 | case 301: 186 | case 304: 187 | case 404: 188 | case 410: 189 | cacheable = YES; 190 | } 191 | 192 | // If the response might be cacheable, look at the "Cache-Control" header in 193 | // the response. 194 | if (cacheable) { 195 | NSString *responseHeader = [response.allHeaderFields[@"Cache-Control"] lowercaseString]; 196 | if ( (responseHeader != nil) && [responseHeader rangeOfString:@"no-store"].location != NSNotFound) { 197 | cacheable = NO; 198 | } 199 | } 200 | 201 | // If we still think it might be cacheable, look at the "Cache-Control" header in 202 | // the request. 203 | if (cacheable) { 204 | NSString *requestHeader = [request.allHTTPHeaderFields[@"Cache-Control"] lowercaseString]; 205 | if ( (requestHeader != nil) 206 | && ([requestHeader rangeOfString:@"no-store"].location != NSNotFound) 207 | && ([requestHeader rangeOfString:@"no-cache"].location != NSNotFound) ) { 208 | cacheable = NO; 209 | } 210 | } 211 | if (cacheable) { 212 | if ([[request.URL.scheme lowercaseString] isEqual:@"https"]) result = NSURLCacheStorageAllowedInMemoryOnly; 213 | else result = NSURLCacheStorageAllowed; 214 | } 215 | 216 | return result; 217 | } 218 | 219 | -(BOOL)parseHeaderStream:(NSInputStream *)theStream { 220 | // check response 221 | _responseMessage = (__bridge CFHTTPMessageRef)[theStream propertyForKey:(NSString *)kCFStreamPropertyHTTPResponseHeader]; 222 | if (!self.responseMessage) return NO; 223 | if (!CFHTTPMessageIsHeaderComplete(self.responseMessage)) return NO; 224 | if (self.HTTPURLResponse) return YES; 225 | 226 | CFIndex httpStatusCode = CFHTTPMessageGetResponseStatusCode(self.responseMessage); 227 | CFStringRef httpVersion = CFHTTPMessageCopyVersion(self.responseMessage); 228 | CFDictionaryRef httpHeaders = CFHTTPMessageCopyAllHeaderFields(self.responseMessage); 229 | _HTTPURLResponse = [[NSHTTPURLResponse alloc] initWithURL:self.request.URL statusCode:httpStatusCode HTTPVersion:(__bridge NSString *)(httpVersion) headerFields:(__bridge NSDictionary *)(httpHeaders)]; 230 | 231 | if (httpStatusCode == 304) { 232 | // there are cached stuff 233 | NSCachedURLResponse *cached = [[NSURLCache sharedURLCache] cachedResponseForRequest:self.request]; 234 | if (cached) { 235 | [self.client URLProtocol:self cachedResponseIsValid:cached]; 236 | [self.client URLProtocol:self didReceiveResponse:cached.response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; 237 | [self.client URLProtocol:self didLoadData:[cached data]]; 238 | [self.client URLProtocolDidFinishLoading:self];// No http body expected 239 | [self stopLoading]; 240 | return NO; 241 | } 242 | 243 | [self.client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain 244 | code:NSURLErrorCannotDecodeContentData 245 | userInfo:nil]]; 246 | return NO; 247 | } 248 | 249 | // handle redirects 250 | if ((httpStatusCode >= 300) && (httpStatusCode <= 307)) { 251 | // redirect 252 | NSMutableURLRequest *newRequest = [self.request mutableCopy]; 253 | newRequest.URL = [[NSURL URLWithString:[self.HTTPURLResponse.allHeaderFields valueForKey:@"Location"] relativeToURL:self.request.URL] absoluteURL]; 254 | 255 | NSDictionary *newCookiesHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:[NSHTTPCookie cookiesWithResponseHeaderFields:self.HTTPURLResponse.allHeaderFields forURL:self.HTTPURLResponse.URL]]; 256 | for (NSString *key in newCookiesHeaderFields) 257 | [newRequest setValue:[newCookiesHeaderFields objectForKey:key] forHTTPHeaderField:key]; 258 | 259 | [self.client URLProtocol:self wasRedirectedToRequest:newRequest redirectResponse:self.HTTPURLResponse]; 260 | [self stopLoading]; 261 | return NO; 262 | } 263 | 264 | // authentication 265 | NSAssert(!self.authChallenge, @"There is already an authentication challenge happening!"); 266 | 267 | if (httpStatusCode == 407) { 268 | // proxy auth 269 | NSURL *proxyURL = [NSURLProtocol propertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self.request]; 270 | if (self.internalHTTPProxyCredential) { 271 | NSURLCredential *credential = self.internalHTTPProxyCredential; 272 | self.internalHTTPProxyCredential = nil; 273 | [self _restartLoadingWithCredential:credential]; 274 | return NO; 275 | } 276 | 277 | CFHTTPAuthenticationRef authentication = CFHTTPAuthenticationCreateFromResponse(kCFAllocatorDefault, self.responseMessage); 278 | NSString *proxyType = NSURLProtectionSpaceHTTPProxy; 279 | if ([proxyURL.scheme hasPrefix:@"socks"]) proxyType = NSURLProtectionSpaceSOCKSProxy; 280 | if ([proxyURL.scheme hasPrefix:@"https"]) proxyType = NSURLProtectionSpaceHTTPSProxy; 281 | 282 | NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithProxyHost:proxyURL.host 283 | port:[proxyURL.port integerValue] 284 | type:proxyType 285 | realm:(__bridge NSString *)(CFHTTPAuthenticationCopyRealm(authentication)) 286 | authenticationMethod:(__bridge NSString *)(CFHTTPAuthenticationCopyMethod(authentication))]; 287 | 288 | self.authChallenge = [[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:protectionSpace 289 | proposedCredential:nil 290 | previousFailureCount:self.authFailureCount 291 | failureResponse:[self.HTTPURLResponse copy] 292 | error:nil 293 | sender:self]; 294 | 295 | [self stopLoading]; 296 | 297 | [self.client URLProtocol:self didReceiveAuthenticationChallenge:self.authChallenge]; 298 | self.authFailureCount++; 299 | _HTTPURLResponse = nil; 300 | return NO; 301 | } 302 | 303 | if (httpStatusCode == 401) { 304 | // user auth 305 | CFHTTPAuthenticationRef authentication = CFHTTPAuthenticationCreateFromResponse(kCFAllocatorDefault, self.responseMessage); 306 | NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:self.HTTPURLResponse.URL.host 307 | port:[self.HTTPURLResponse.URL.port integerValue] 308 | protocol:self.HTTPURLResponse.URL.scheme 309 | realm:(__bridge NSString *)(CFHTTPAuthenticationCopyRealm(authentication)) 310 | authenticationMethod:(__bridge NSString *)(CFHTTPAuthenticationCopyMethod(authentication))]; 311 | 312 | self.authChallenge = [[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:protectionSpace 313 | proposedCredential:nil 314 | previousFailureCount:self.authFailureCount 315 | failureResponse:[self.HTTPURLResponse copy] 316 | error:nil 317 | sender:self]; 318 | [self stopLoading]; 319 | 320 | [self.client URLProtocol:self didReceiveAuthenticationChallenge:self.authChallenge]; 321 | self.authFailureCount++; 322 | _HTTPURLResponse = nil; 323 | return NO; 324 | } 325 | 326 | NSURLCacheStoragePolicy policy = [self cachePolicyForRequest:self.request response:self.HTTPURLResponse]; 327 | [self.client URLProtocol:self didReceiveResponse:self.HTTPURLResponse cacheStoragePolicy:policy]; 328 | 329 | return YES; 330 | } 331 | 332 | -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { 333 | if (aStream != self.HTTPResponseStream) return; 334 | NSInputStream *theStream = (NSInputStream *)aStream; 335 | 336 | BOOL proceed = YES; 337 | if (!self.HTTPURLResponse) 338 | proceed = [self parseHeaderStream:theStream]; 339 | 340 | switch (eventCode) { 341 | case NSStreamEventHasBytesAvailable: { 342 | while (theStream.hasBytesAvailable) { 343 | uint8_t buf[1024]; 344 | NSInteger len = [theStream read:buf maxLength:1024]; 345 | if (len == 0) continue; 346 | 347 | NSData *data = [NSData dataWithBytes:buf length:len]; 348 | 349 | if (!proceed) continue; 350 | [self.client URLProtocol:self didLoadData:data]; 351 | } 352 | } 353 | break; 354 | 355 | case NSStreamEventEndEncountered: 356 | if (!proceed) return; 357 | [self.client URLProtocolDidFinishLoading:self]; 358 | break; 359 | 360 | case NSStreamEventErrorOccurred: 361 | if (!proceed) return; 362 | 363 | [self.client URLProtocol:self didFailWithError:aStream.streamError]; 364 | [self stopLoading]; 365 | break; 366 | 367 | default: 368 | break; 369 | } 370 | } 371 | 372 | @end 373 | 374 | #pragma mark - Categories 375 | 376 | @implementation NSURLRequest (LLHTTPProxyURLProtocol) 377 | -(NSURL *)proxyServerURL { return [NSURLProtocol propertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self]; } 378 | -(BOOL)validatesCertificateChain { return ([NSURLProtocol propertyForKey:(NSString *)kCFStreamSSLValidatesCertificateChain inRequest:self]) ? [[NSURLProtocol propertyForKey:(NSString *)kCFStreamSSLValidatesCertificateChain inRequest:self] boolValue] : YES; } 379 | -(NSArray *)certificateChain { return [NSURLProtocol propertyForKey:(NSString *)kCFStreamSSLCertificates inRequest:self]; } 380 | @end 381 | 382 | @implementation NSMutableURLRequest (LLHTTPProxyURLProtocol) 383 | -(void)setValidatesCertificateChain:(BOOL)validatesCertificateChain { 384 | if (self.validatesCertificateChain == validatesCertificateChain) return; 385 | [NSURLProtocol setProperty:@(validatesCertificateChain) forKey:(NSString *)kCFStreamSSLValidatesCertificateChain inRequest:self]; 386 | } 387 | 388 | -(void)setCertificateChain:(NSArray *)certificateChain { 389 | if (self.certificateChain == certificateChain) return; 390 | [NSURLProtocol setProperty:certificateChain forKey:(NSString *)kCFStreamSSLCertificates inRequest:self]; 391 | } 392 | 393 | -(void)setProxyServerURL:(NSURL *)proxyServerURL { 394 | if (!proxyServerURL) { 395 | [NSURLProtocol removePropertyForKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self]; 396 | return; 397 | } 398 | 399 | if ([self.proxyServerURL isEqual:proxyServerURL]) return; 400 | [NSURLProtocol setProperty:[proxyServerURL copy] forKey:LLHTTPProxyURLProtocolProxyServerKey inRequest:self]; 401 | } 402 | @end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LLHTTPProxyURLProtocol 2 | 3 | This is a `NSURLProtocol` subclass that allows NSURLRequests to be sent over a specified proxy. Because it is a `NSURLProtocol`, regular libraries that make use of `NSURLConnection` for URL loading should be able to transparently use it. 4 | 5 | It will take over URL loading for any `NSURLRequest` that has set the proxy server address property. 6 | 7 | ## Proxy Support 8 | Currently it supports the following types of proxies (that are available in CFNetwork) 9 | 10 | - Socks 4 11 | - Socks 5 12 | - HTTP 13 | - HTTPS 14 | 15 | Proxy auto configuration via a URL will also be eventually supported. 16 | 17 | ## Design Goals 18 | 19 | - Allow transparent usage of NSURLConnection 20 | - Support `http` and `https` URL loading 21 | - Full support for `NSURLAuthenticationChallenge` type events 22 | 23 | ## Todo 24 | 25 | - Figure out how to get `NSURLProtectionSpace` that is for SSL connections ([It seems we need to go lower level and implement our own CFHTTPStream]( https://developer.apple.com/library/ios/technotes/tn2232/_index.html#//apple_ref/doc/uid/DTS40012884-CH1-CFHTTPSTREAM)) 26 | --------------------------------------------------------------------------------