├── .gitignore ├── Demo ├── MJGHTTPRequestDemo-Info.plist ├── MJGHTTPRequestDemo-Prefix.pch ├── MJGHTTPRequestDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Source │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── BeerMapApiRequest.h │ ├── BeerMapApiRequest.m │ ├── MJGHTTPRequestDemoViewController.h │ ├── MJGHTTPRequestDemoViewController.m │ └── MJGHTTPRequestDemoViewController.xib └── main.m ├── LICENSE ├── README.markdown └── Source ├── MJGHTTPDownload.h ├── MJGHTTPDownload.m ├── MJGHTTPRequest.h ├── MJGHTTPRequest.m ├── NSDictionary-HTTP.h ├── NSDictionary-HTTP.m ├── NSString-HTTP.h └── NSString-HTTP.m /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.pbxuser 3 | *.mode1v3 4 | *.mode2v3 5 | *.pbxuser 6 | *.perspective 7 | *.perspectivev3 8 | *.xcuserdatad 9 | 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /Demo/MJGHTTPRequestDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Demo/MJGHTTPRequestDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #import 4 | #endif 5 | -------------------------------------------------------------------------------- /Demo/MJGHTTPRequestDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C9020A2314A222A500EF6DF8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9020A2214A222A500EF6DF8 /* UIKit.framework */; }; 11 | C9020A2514A222A500EF6DF8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9020A2414A222A500EF6DF8 /* Foundation.framework */; }; 12 | C9020A2714A222A500EF6DF8 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9020A2614A222A500EF6DF8 /* CoreGraphics.framework */; }; 13 | C9020A4314A225E700EF6DF8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C9020A3D14A225E700EF6DF8 /* main.m */; }; 14 | C9020A4514A225E700EF6DF8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C9020A4214A225E700EF6DF8 /* AppDelegate.m */; }; 15 | C9020A4E14A2263400EF6DF8 /* MJGHTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = C9020A4B14A2263400EF6DF8 /* MJGHTTPRequest.m */; }; 16 | C9020A4F14A2263400EF6DF8 /* NSDictionary-HTTP.m in Sources */ = {isa = PBXBuildFile; fileRef = C9020A4D14A2263400EF6DF8 /* NSDictionary-HTTP.m */; }; 17 | C9020A5A14A22FC000EF6DF8 /* BeerMapApiRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = C9020A5914A22FC000EF6DF8 /* BeerMapApiRequest.m */; }; 18 | C9020A5E14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C9020A5C14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.m */; }; 19 | C9020A5F14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C9020A5D14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.xib */; }; 20 | C9EB549F14A5E22F003B4206 /* NSString-HTTP.m in Sources */ = {isa = PBXBuildFile; fileRef = C9EB549E14A5E22F003B4206 /* NSString-HTTP.m */; }; 21 | C9EC378C14B9CDDF00D82F67 /* MJGHTTPDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = C9EC378B14B9CDDF00D82F67 /* MJGHTTPDownload.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXFileReference section */ 25 | C9020A1E14A222A500EF6DF8 /* MJGHTTPRequestDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MJGHTTPRequestDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 26 | C9020A2214A222A500EF6DF8 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 27 | C9020A2414A222A500EF6DF8 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 28 | C9020A2614A222A500EF6DF8 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 29 | C9020A3D14A225E700EF6DF8 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = SOURCE_ROOT; }; 30 | C9020A3E14A225E700EF6DF8 /* MJGHTTPRequestDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "MJGHTTPRequestDemo-Info.plist"; sourceTree = SOURCE_ROOT; }; 31 | C9020A3F14A225E700EF6DF8 /* MJGHTTPRequestDemo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MJGHTTPRequestDemo-Prefix.pch"; sourceTree = SOURCE_ROOT; }; 32 | C9020A4114A225E700EF6DF8 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | C9020A4214A225E700EF6DF8 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | C9020A4A14A2263400EF6DF8 /* MJGHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJGHTTPRequest.h; sourceTree = ""; }; 35 | C9020A4B14A2263400EF6DF8 /* MJGHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJGHTTPRequest.m; sourceTree = ""; }; 36 | C9020A4C14A2263400EF6DF8 /* NSDictionary-HTTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary-HTTP.h"; sourceTree = ""; }; 37 | C9020A4D14A2263400EF6DF8 /* NSDictionary-HTTP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary-HTTP.m"; sourceTree = ""; }; 38 | C9020A5814A22FC000EF6DF8 /* BeerMapApiRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BeerMapApiRequest.h; sourceTree = ""; }; 39 | C9020A5914A22FC000EF6DF8 /* BeerMapApiRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BeerMapApiRequest.m; sourceTree = ""; }; 40 | C9020A5B14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJGHTTPRequestDemoViewController.h; sourceTree = ""; }; 41 | C9020A5C14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJGHTTPRequestDemoViewController.m; sourceTree = ""; }; 42 | C9020A5D14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MJGHTTPRequestDemoViewController.xib; sourceTree = ""; }; 43 | C9EB549D14A5E22F003B4206 /* NSString-HTTP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString-HTTP.h"; sourceTree = ""; }; 44 | C9EB549E14A5E22F003B4206 /* NSString-HTTP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString-HTTP.m"; sourceTree = ""; }; 45 | C9EC378A14B9CDDF00D82F67 /* MJGHTTPDownload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJGHTTPDownload.h; sourceTree = ""; }; 46 | C9EC378B14B9CDDF00D82F67 /* MJGHTTPDownload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJGHTTPDownload.m; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | C9020A1B14A222A500EF6DF8 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | C9020A2314A222A500EF6DF8 /* UIKit.framework in Frameworks */, 55 | C9020A2514A222A500EF6DF8 /* Foundation.framework in Frameworks */, 56 | C9020A2714A222A500EF6DF8 /* CoreGraphics.framework in Frameworks */, 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | C9020A1314A222A500EF6DF8 = { 64 | isa = PBXGroup; 65 | children = ( 66 | C9020A4814A2262900EF6DF8 /* MJGHTTPRequest */, 67 | C9020A2814A222A500EF6DF8 /* MJGHTTPRequestDemo */, 68 | C9020A2114A222A500EF6DF8 /* Frameworks */, 69 | C9020A1F14A222A500EF6DF8 /* Products */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | C9020A1F14A222A500EF6DF8 /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | C9020A1E14A222A500EF6DF8 /* MJGHTTPRequestDemo.app */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | C9020A2114A222A500EF6DF8 /* Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | C9020A2214A222A500EF6DF8 /* UIKit.framework */, 85 | C9020A2414A222A500EF6DF8 /* Foundation.framework */, 86 | C9020A2614A222A500EF6DF8 /* CoreGraphics.framework */, 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | C9020A2814A222A500EF6DF8 /* MJGHTTPRequestDemo */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | C9020A4014A225E700EF6DF8 /* Source */, 95 | C9020A4714A2260100EF6DF8 /* Supporting Files */, 96 | ); 97 | path = MJGHTTPRequestDemo; 98 | sourceTree = ""; 99 | }; 100 | C9020A4014A225E700EF6DF8 /* Source */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | C9020A4114A225E700EF6DF8 /* AppDelegate.h */, 104 | C9020A4214A225E700EF6DF8 /* AppDelegate.m */, 105 | C9020A5814A22FC000EF6DF8 /* BeerMapApiRequest.h */, 106 | C9020A5914A22FC000EF6DF8 /* BeerMapApiRequest.m */, 107 | C9020A5B14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.h */, 108 | C9020A5C14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.m */, 109 | C9020A5D14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.xib */, 110 | ); 111 | path = Source; 112 | sourceTree = SOURCE_ROOT; 113 | }; 114 | C9020A4714A2260100EF6DF8 /* Supporting Files */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | C9020A3D14A225E700EF6DF8 /* main.m */, 118 | C9020A3E14A225E700EF6DF8 /* MJGHTTPRequestDemo-Info.plist */, 119 | C9020A3F14A225E700EF6DF8 /* MJGHTTPRequestDemo-Prefix.pch */, 120 | ); 121 | name = "Supporting Files"; 122 | sourceTree = ""; 123 | }; 124 | C9020A4814A2262900EF6DF8 /* MJGHTTPRequest */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | C9020A4914A2263400EF6DF8 /* Source */, 128 | ); 129 | name = MJGHTTPRequest; 130 | sourceTree = ""; 131 | }; 132 | C9020A4914A2263400EF6DF8 /* Source */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | C9020A4A14A2263400EF6DF8 /* MJGHTTPRequest.h */, 136 | C9020A4B14A2263400EF6DF8 /* MJGHTTPRequest.m */, 137 | C9EC378A14B9CDDF00D82F67 /* MJGHTTPDownload.h */, 138 | C9EC378B14B9CDDF00D82F67 /* MJGHTTPDownload.m */, 139 | C9020A4C14A2263400EF6DF8 /* NSDictionary-HTTP.h */, 140 | C9020A4D14A2263400EF6DF8 /* NSDictionary-HTTP.m */, 141 | C9EB549D14A5E22F003B4206 /* NSString-HTTP.h */, 142 | C9EB549E14A5E22F003B4206 /* NSString-HTTP.m */, 143 | ); 144 | name = Source; 145 | path = ../Source; 146 | sourceTree = ""; 147 | }; 148 | /* End PBXGroup section */ 149 | 150 | /* Begin PBXNativeTarget section */ 151 | C9020A1D14A222A500EF6DF8 /* MJGHTTPRequestDemo */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = C9020A3614A222A500EF6DF8 /* Build configuration list for PBXNativeTarget "MJGHTTPRequestDemo" */; 154 | buildPhases = ( 155 | C9020A1A14A222A500EF6DF8 /* Sources */, 156 | C9020A1B14A222A500EF6DF8 /* Frameworks */, 157 | C9020A1C14A222A500EF6DF8 /* Resources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | ); 163 | name = MJGHTTPRequestDemo; 164 | productName = MJGHTTPRequestDemo; 165 | productReference = C9020A1E14A222A500EF6DF8 /* MJGHTTPRequestDemo.app */; 166 | productType = "com.apple.product-type.application"; 167 | }; 168 | /* End PBXNativeTarget section */ 169 | 170 | /* Begin PBXProject section */ 171 | C9020A1514A222A500EF6DF8 /* Project object */ = { 172 | isa = PBXProject; 173 | attributes = { 174 | LastUpgradeCheck = 0420; 175 | }; 176 | buildConfigurationList = C9020A1814A222A500EF6DF8 /* Build configuration list for PBXProject "MJGHTTPRequestDemo" */; 177 | compatibilityVersion = "Xcode 3.2"; 178 | developmentRegion = English; 179 | hasScannedForEncodings = 0; 180 | knownRegions = ( 181 | en, 182 | ); 183 | mainGroup = C9020A1314A222A500EF6DF8; 184 | productRefGroup = C9020A1F14A222A500EF6DF8 /* Products */; 185 | projectDirPath = ""; 186 | projectRoot = ""; 187 | targets = ( 188 | C9020A1D14A222A500EF6DF8 /* MJGHTTPRequestDemo */, 189 | ); 190 | }; 191 | /* End PBXProject section */ 192 | 193 | /* Begin PBXResourcesBuildPhase section */ 194 | C9020A1C14A222A500EF6DF8 /* Resources */ = { 195 | isa = PBXResourcesBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | C9020A5F14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.xib in Resources */, 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | /* End PBXResourcesBuildPhase section */ 203 | 204 | /* Begin PBXSourcesBuildPhase section */ 205 | C9020A1A14A222A500EF6DF8 /* Sources */ = { 206 | isa = PBXSourcesBuildPhase; 207 | buildActionMask = 2147483647; 208 | files = ( 209 | C9020A4314A225E700EF6DF8 /* main.m in Sources */, 210 | C9020A4514A225E700EF6DF8 /* AppDelegate.m in Sources */, 211 | C9020A4E14A2263400EF6DF8 /* MJGHTTPRequest.m in Sources */, 212 | C9020A4F14A2263400EF6DF8 /* NSDictionary-HTTP.m in Sources */, 213 | C9020A5A14A22FC000EF6DF8 /* BeerMapApiRequest.m in Sources */, 214 | C9020A5E14A233B900EF6DF8 /* MJGHTTPRequestDemoViewController.m in Sources */, 215 | C9EB549F14A5E22F003B4206 /* NSString-HTTP.m in Sources */, 216 | C9EC378C14B9CDDF00D82F67 /* MJGHTTPDownload.m in Sources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXSourcesBuildPhase section */ 221 | 222 | /* Begin XCBuildConfiguration section */ 223 | C9020A3414A222A500EF6DF8 /* Debug */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ALWAYS_SEARCH_USER_PATHS = NO; 227 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 228 | CLANG_ENABLE_OBJC_ARC = YES; 229 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 230 | COPY_PHASE_STRIP = NO; 231 | GCC_C_LANGUAGE_STANDARD = gnu99; 232 | GCC_DYNAMIC_NO_PIC = NO; 233 | GCC_OPTIMIZATION_LEVEL = 0; 234 | GCC_PREPROCESSOR_DEFINITIONS = ( 235 | "DEBUG=1", 236 | "$(inherited)", 237 | ); 238 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 239 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 240 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNUSED_VARIABLE = YES; 243 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 244 | SDKROOT = iphoneos; 245 | }; 246 | name = Debug; 247 | }; 248 | C9020A3514A222A500EF6DF8 /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ALWAYS_SEARCH_USER_PATHS = NO; 252 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 253 | CLANG_ENABLE_OBJC_ARC = YES; 254 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 255 | COPY_PHASE_STRIP = YES; 256 | GCC_C_LANGUAGE_STANDARD = gnu99; 257 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 258 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 259 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 260 | GCC_WARN_UNUSED_VARIABLE = YES; 261 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 262 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 263 | SDKROOT = iphoneos; 264 | VALIDATE_PRODUCT = YES; 265 | }; 266 | name = Release; 267 | }; 268 | C9020A3714A222A500EF6DF8 /* Debug */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 272 | GCC_PREFIX_HEADER = "MJGHTTPRequestDemo-Prefix.pch"; 273 | INFOPLIST_FILE = "MJGHTTPRequestDemo-Info.plist"; 274 | PRODUCT_NAME = "$(TARGET_NAME)"; 275 | WRAPPER_EXTENSION = app; 276 | }; 277 | name = Debug; 278 | }; 279 | C9020A3814A222A500EF6DF8 /* Release */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 283 | GCC_PREFIX_HEADER = "MJGHTTPRequestDemo-Prefix.pch"; 284 | INFOPLIST_FILE = "MJGHTTPRequestDemo-Info.plist"; 285 | PRODUCT_NAME = "$(TARGET_NAME)"; 286 | WRAPPER_EXTENSION = app; 287 | }; 288 | name = Release; 289 | }; 290 | /* End XCBuildConfiguration section */ 291 | 292 | /* Begin XCConfigurationList section */ 293 | C9020A1814A222A500EF6DF8 /* Build configuration list for PBXProject "MJGHTTPRequestDemo" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | C9020A3414A222A500EF6DF8 /* Debug */, 297 | C9020A3514A222A500EF6DF8 /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | C9020A3614A222A500EF6DF8 /* Build configuration list for PBXNativeTarget "MJGHTTPRequestDemo" */ = { 303 | isa = XCConfigurationList; 304 | buildConfigurations = ( 305 | C9020A3714A222A500EF6DF8 /* Debug */, 306 | C9020A3814A222A500EF6DF8 /* Release */, 307 | ); 308 | defaultConfigurationIsVisible = 0; 309 | defaultConfigurationName = Release; 310 | }; 311 | /* End XCConfigurationList section */ 312 | }; 313 | rootObject = C9020A1514A222A500EF6DF8 /* Project object */; 314 | } 315 | -------------------------------------------------------------------------------- /Demo/MJGHTTPRequestDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Source/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | @interface AppDelegate : UIResponder 32 | 33 | @property (strong, nonatomic) UIWindow *window; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Demo/Source/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import "AppDelegate.h" 30 | 31 | #import "MJGHTTPRequestDemoViewController.h" 32 | 33 | @implementation AppDelegate 34 | 35 | @synthesize window = _window; 36 | 37 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 38 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 39 | self.window.backgroundColor = [UIColor whiteColor]; 40 | 41 | MJGHTTPRequestDemoViewController *viewController = [[MJGHTTPRequestDemoViewController alloc] initWithNibName:nil bundle:nil]; 42 | self.window.rootViewController = viewController; 43 | 44 | [self.window makeKeyAndVisible]; 45 | return YES; 46 | } 47 | 48 | - (void)applicationWillResignActive:(UIApplication *)application { 49 | } 50 | 51 | - (void)applicationDidEnterBackground:(UIApplication *)application { 52 | } 53 | 54 | - (void)applicationWillEnterForeground:(UIApplication *)application { 55 | } 56 | 57 | - (void)applicationDidBecomeActive:(UIApplication *)application { 58 | } 59 | 60 | - (void)applicationWillTerminate:(UIApplication *)application { 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Demo/Source/BeerMapApiRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // BeerMapApiRequest.h 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | /** 30 | * Example of how to use MJGHTTPRequest by creating a class that can talk to the BeerMap API. 31 | */ 32 | 33 | #import "MJGHTTPRequest.h" 34 | 35 | @interface BeerMapApiRequest : MJGHTTPRequest 36 | 37 | - (id)initWithApiPath:(NSString*)apiPath requestMethod:(MJGHTTPRequestMethod)method; 38 | 39 | // Methods to override from MJGHTTPRequest 40 | - (NSString*)url; 41 | - (NSDictionary*)extraParameters; 42 | - (NSDictionary*)extraGetParameters; 43 | - (id)handleResult:(NSData*)result error:(NSError**)error; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Demo/Source/BeerMapApiRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // BeerMapApiRequest.m 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import "BeerMapApiRequest.h" 30 | 31 | @interface BeerMapApiRequest () 32 | @property (nonatomic, copy) NSString *apiPath; 33 | @end 34 | 35 | @implementation BeerMapApiRequest 36 | 37 | @synthesize apiPath; 38 | 39 | #pragma mark - 40 | 41 | - (id)initWithApiPath:(NSString*)inApiPath requestMethod:(MJGHTTPRequestMethod)method { 42 | if ((self = [super initWithRequestMethod:method])) { 43 | self.apiPath = inApiPath; 44 | } 45 | return self; 46 | } 47 | 48 | 49 | #pragma mark - 50 | 51 | - (NSString*)url { 52 | return [NSString stringWithFormat:@"http://bmapi.mynet.org.uk/v2/%@", apiPath]; 53 | } 54 | 55 | - (NSDictionary*)extraParameters { 56 | return nil; 57 | } 58 | 59 | - (NSDictionary*)extraGetParameters { 60 | return [NSDictionary dictionaryWithObjectsAndKeys: 61 | @"json", @"format", 62 | nil]; 63 | } 64 | 65 | - (id)handleResult:(NSData*)result error:(NSError**)error { 66 | NSError *jsonError = nil; 67 | NSDictionary *outResult = [NSJSONSerialization JSONObjectWithData:result 68 | options:0 69 | error:&jsonError]; 70 | if (jsonError) { 71 | if (error) { 72 | *error = jsonError; 73 | } 74 | return nil; 75 | } 76 | 77 | return outResult; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /Demo/Source/MJGHTTPRequestDemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJGHTTPRequestDemoViewController.h 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | @interface MJGHTTPRequestDemoViewController : UIViewController 32 | 33 | @property (nonatomic, strong) IBOutlet UITextView *outputText; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Demo/Source/MJGHTTPRequestDemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJGHTTPRequestDemoViewController.m 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import "MJGHTTPRequestDemoViewController.h" 30 | 31 | #import "BeerMapApiRequest.h" 32 | 33 | @implementation MJGHTTPRequestDemoViewController 34 | 35 | @synthesize outputText; 36 | 37 | #pragma mark - 38 | 39 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 40 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 41 | } 42 | return self; 43 | } 44 | 45 | - (void)didReceiveMemoryWarning { 46 | [super didReceiveMemoryWarning]; 47 | } 48 | 49 | 50 | #pragma mark - View lifecycle 51 | 52 | - (void)viewDidLoad { 53 | [super viewDidLoad]; 54 | 55 | BeerMapApiRequest *request = [[BeerMapApiRequest alloc] initWithApiPath:@"beer/show" requestMethod:MJGHTTPRequestMethodGET]; 56 | request.parameters = [NSDictionary dictionaryWithObjectsAndKeys:@"651", @"id", nil]; 57 | [request startWithHandler:^(id result, NSHTTPURLResponse *response, NSError *error){ 58 | if (!error) { 59 | // BeerMapApiRequest returns an NSDictionary, but we'll just output it's description anyway 60 | self.outputText.text = [result description]; 61 | } else { 62 | // Ooops! Error! 63 | self.outputText.text = [error description]; 64 | } 65 | }]; 66 | } 67 | 68 | - (void)viewDidUnload { 69 | [super viewDidUnload]; 70 | self.outputText = nil; 71 | } 72 | 73 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 74 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Demo/Source/MJGHTTPRequestDemoViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11C74 6 | 1938 7 | 1138.23 8 | 567.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUITextView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 274 41 | {320, 460} 42 | 43 | 44 | _NS:639 45 | 46 | 1 47 | MSAxIDEAA 48 | 49 | YES 50 | YES 51 | IBCocoaTouchFramework 52 | 53 | 54 | 2 55 | IBCocoaTouchFramework 56 | 57 | 58 | 1 59 | 14 60 | 61 | 62 | Helvetica 63 | 14 64 | 16 65 | 66 | 67 | 68 | {{0, 20}, {320, 460}} 69 | 70 | 71 | 72 | 73 | 3 74 | MQA 75 | 76 | 2 77 | 78 | 79 | 80 | IBCocoaTouchFramework 81 | 82 | 83 | 84 | 85 | 86 | 87 | view 88 | 89 | 90 | 91 | 3 92 | 93 | 94 | 95 | outputText 96 | 97 | 98 | 99 | 6 100 | 101 | 102 | 103 | 104 | 105 | 0 106 | 107 | 108 | 109 | 110 | 111 | 1 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -1 120 | 121 | 122 | File's Owner 123 | 124 | 125 | -2 126 | 127 | 128 | 129 | 130 | 5 131 | 132 | 133 | 134 | 135 | 136 | 137 | MJGHTTPRequestDemoViewController 138 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 139 | UIResponder 140 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 141 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 142 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 143 | 144 | 145 | 146 | 147 | 148 | 6 149 | 150 | 151 | 152 | 153 | MJGHTTPRequestDemoViewController 154 | UIViewController 155 | 156 | outputText 157 | UITextView 158 | 159 | 160 | outputText 161 | 162 | outputText 163 | UITextView 164 | 165 | 166 | 167 | IBProjectSource 168 | ./Classes/MJGHTTPRequestDemoViewController.h 169 | 170 | 171 | 172 | 173 | 0 174 | IBCocoaTouchFramework 175 | YES 176 | 3 177 | 933 178 | 179 | 180 | -------------------------------------------------------------------------------- /Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | #import "AppDelegate.h" 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | @autoreleasepool { 36 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Matt Galloway. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this 7 | list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # MJGHTTPRequest 2 | 3 | ## Introduction 4 | 5 | MJGHTTPRequest is a class designed to be subclassed to take the pain out of performing HTTP 6 | requests on iOS. Most HTTP APIs have a base URL that's the same (e.g. api.twitter.com) and take 7 | certain parameters. They also usually return a given format of data such as JSON or XML. 8 | MJGHTTPRequest enables you to create your own class to talk to these APIs and handle all the HTTP 9 | level things for you. All you need to do is hook into whatever mechanism you want to handle the 10 | returned data which might be passing it through a JSON or XML deserialiser for example. 11 | 12 | ## Features 13 | 14 | * GET & POST HTTP requests. 15 | * URL encoded, multipart & raw POST formats. 16 | * Customisation hooks to act on the request at its various stages. 17 | 18 | ## Why should I use MJGHTTPRequest? 19 | 20 | MJGHTTPRequest is useful for when you have a project that is using an HTTP API and you find 21 | yourself writing the same code over and over again. Whether it's the same code using standard 22 | Cocoa APIs or some other asynchronous HTTP request framework, MJGHTTPRequest is the perfect 23 | replacement to take the pain out of all that duplicated code. It gives you the flexibility to 24 | write once a class that conforms to the spec laid out by your HTTP API and then use it everywhere! 25 | 26 | ## License 27 | 28 | MJGHTTPRequest uses the 2-clause BSD license. So you should be free to use it pretty much however 29 | you want. Contact me if you require further information. 30 | 31 | Copyright (c) 2011 Matt Galloway. All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | 1. Redistributions of source code must retain the above copyright notice, this 37 | list of conditions and the following disclaimer. 38 | 39 | 2. Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 43 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 44 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 46 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 47 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 49 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 50 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 51 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 | 54 | ## Automatic Reference Counting (ARC) 55 | 56 | This project uses ARC. 57 | 58 | ## Author 59 | 60 | MJGHTTPRequest is written and maintained by Matt Galloway . 61 | 62 | ## Projects using MJGHTTPRequest 63 | 64 | * BeerMap - http://www.beermap.co/ 65 | * Kindmags Magazine Framework - http://www.kindmags.com/ 66 | 67 | Are you using MJGHTTPRequest? If so, contact me and I'll add you to the list. 68 | 69 | ## How to use 70 | 71 | As an example, we will assume there is a HTTP API which is based at http://api.example.com/v1/ 72 | which has the following methods: 73 | 74 | * `search` - takes a single paramter `term` and returns an array of results. Result will be found in 75 | under the key `results` in the returned object. 76 | * `upload` - takes files to be uploaded to the server and returns success or failure. 77 | 78 | In addition, all methods are required to have a `format` paremeter set in the query part of the URL 79 | to indicate either `json` or `xml` return types. We will use `json`. The API defines that every 80 | request will return a JSON object with the data in it. 81 | 82 | ### Adding MJGHTTPRequest to your project 83 | 84 | All you need to do to get started is to add everything in the `Source` folder to your project. 85 | 86 | ### Subclassing MJGHTTPRequest 87 | 88 | 1. Create a class which inherits from `MJGHTTPRequest`: 89 | 90 | #import "MJGHTTPRequest.h" 91 | @interface MyApiRequest : MJGHTTPRequest 92 | @property (nonatomic, strong) NSString *path; 93 | @end 94 | 95 | 1. Implement the required methods: 96 | 97 | @implementation MyApiRequest 98 | 99 | @synthesize path; 100 | 101 | - (NSString*)url { 102 | return [NSString stringWithFormat:@"http://api.example.com/v1/%@", path]; 103 | } 104 | 105 | - (NSDictionary*)extraParameters { 106 | return nil; 107 | } 108 | 109 | - (NSDictionary*)extraGetParameters { 110 | return [NSDictionary dictionaryWithObjectsAndKeys: 111 | @"json", @"format", 112 | nil]; 113 | } 114 | 115 | - (id)handleResult:(NSData*)result error:(NSError**)error { 116 | // We know our API is returning a JSON object, so lets deserialise it and return the object 117 | 118 | NSError *jsonError = nil; 119 | NSDictionary *outResult = [NSJSONSerialization JSONObjectWithData:result 120 | options:0 121 | error:&jsonError]; 122 | if (jsonError) { 123 | if (error) { 124 | *error = jsonError; 125 | } 126 | return nil; 127 | } 128 | 129 | return outResult; 130 | } 131 | @end 132 | 133 | ### Using your subclass 134 | 135 | 1. Now use the subclass to peform a search: 136 | 137 | MyApiRequest *request = [[MyApiRequest alloc] initWithRequestMethod:MJGHTTPRequestMethodGET]; 138 | request.path = @"search"; 139 | request.parameters = [NSDictionary dictionaryWithObjectsAndKeys:@"bunnies", @"term", nil]; 140 | [request startWithHandler:^(id result, NSHTTPURLResponse *response, NSError *error){ 141 | if (!error) { 142 | // Yay the request worked! 143 | NSArray *results = [(NSDictionary*)result objectForKey:@"results"]; 144 | NSLog(@"Results:\n%@", results); 145 | } else { 146 | // Ooops! Error! 147 | } 148 | }]; 149 | 150 | 1. And now upload a picture: 151 | 152 | UIImage *image = ; 153 | MyApiRequest *request = [[MyApiRequest alloc] initWithRequestMethod:MJGHTTPRequestMethodPOST]; 154 | request.postMethod = MJGHTTPRequestPOSTMethodFormData; 155 | request.path = @"upload"; 156 | [request addFileData:UIImagePNGRepresentation(image) 157 | forKey:@"image" 158 | withFilename:@"image.png" 159 | type:@"image/png"]; 160 | [request startWithHandler:^(id result, NSHTTPURLResponse *response, NSError *error){ 161 | if (!error) { 162 | // Yay the request worked! 163 | } else { 164 | // Ooops! Error! 165 | } 166 | }]; 167 | -------------------------------------------------------------------------------- /Source/MJGHTTPDownload.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJGHTTPDownload.h 3 | // MJGHTTPRequest 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | typedef void(^MJGHTTPDownloadHandler)(NSString *filename, NSHTTPURLResponse *response, NSError *error); 32 | typedef void(^MJGHTTPDownloadProgressHandler)(float progress); 33 | 34 | @interface MJGHTTPDownload : NSObject 35 | 36 | @property (nonatomic, assign, readonly) float progress; 37 | 38 | - (id)initWithURL:(NSString*)url downloadFilename:(NSString*)filename; 39 | + (MJGHTTPDownload*)requestWithURL:(NSString*)url downloadFilename:(NSString*)filename; 40 | 41 | - (void)startWithHandler:(MJGHTTPDownloadHandler)handler; 42 | - (void)startWithHandler:(MJGHTTPDownloadHandler)handler progressHandler:(MJGHTTPDownloadProgressHandler)progressHandler; 43 | - (void)cancel; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Source/MJGHTTPDownload.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJGHTTPDownload.m 3 | // MJGHTTPRequest 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #if ! __has_feature(objc_arc) 30 | #error This file requires ARC to be enabled. Either enable ARC for the entire project or use -fobjc-arc flag. 31 | #endif 32 | 33 | #import "MJGHTTPDownload.h" 34 | 35 | @interface MJGHTTPDownload () 36 | @property (nonatomic, copy) MJGHTTPDownloadHandler handler; 37 | @property (nonatomic, copy) MJGHTTPDownloadProgressHandler progressHandler; 38 | 39 | @property (nonatomic, copy) NSString *url; 40 | @property (nonatomic, copy) NSString *filename; 41 | 42 | @property (nonatomic, strong) NSURLConnection *connection; 43 | @property (nonatomic, strong) NSHTTPURLResponse *response; 44 | @property (nonatomic, strong) NSFileHandle *responseFileHandle; 45 | @property (nonatomic, assign) long long expectedContentLength; 46 | @property (nonatomic, assign) long long downloadedLength; 47 | 48 | - (void)failWithError:(NSError*)error; 49 | - (void)finish; 50 | @end 51 | 52 | @implementation MJGHTTPDownload 53 | 54 | @synthesize handler = _handler, progressHandler = _progressHandler; 55 | @synthesize url = _url, filename = _filename; 56 | @synthesize connection = _connection, response = _response, responseFileHandle = _responseFileHandle, expectedContentLength = _expectedContentLength, downloadedLength = _downloadedLength; 57 | 58 | #pragma mark - 59 | 60 | - (id)initWithURL:(NSString*)inUrl downloadFilename:(NSString*)inFilename { 61 | if ((self = [self init])) { 62 | _url = [inUrl copy]; 63 | _filename = [inFilename copy]; 64 | } 65 | return self; 66 | } 67 | 68 | + (MJGHTTPDownload*)requestWithURL:(NSString*)inUrl downloadFilename:(NSString*)inFilename { 69 | return [[MJGHTTPDownload alloc] initWithURL:inUrl downloadFilename:inFilename]; 70 | } 71 | 72 | 73 | #pragma mark - Custom accessors 74 | 75 | - (float)progress { 76 | return (float)((double)_downloadedLength / (double)_expectedContentLength); 77 | } 78 | 79 | 80 | #pragma mark - 81 | 82 | - (void)startWithHandler:(MJGHTTPDownloadHandler)inHandler { 83 | [self startWithHandler:inHandler progressHandler:nil]; 84 | } 85 | 86 | - (void)startWithHandler:(MJGHTTPDownloadHandler)inHandler progressHandler:(MJGHTTPDownloadProgressHandler)inProgressHandler { 87 | self.handler = inHandler; 88 | self.progressHandler = inProgressHandler; 89 | 90 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:_url] 91 | cachePolicy:NSURLRequestReloadIgnoringLocalCacheData 92 | timeoutInterval:30.0]; 93 | [request setHTTPMethod:@"GET"]; 94 | 95 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 96 | if ([fileManager fileExistsAtPath:_filename]) { 97 | // Try to restart the download 98 | NSError *error = nil; 99 | NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:_filename error:&error]; 100 | NSNumber *fileSize = [fileAttributes objectForKey:NSFileSize]; 101 | if (!error && fileSize) { 102 | unsigned long long bytes = [fileSize unsignedLongLongValue]; 103 | [request setValue:[NSString stringWithFormat:@"bytes=%llu-", bytes] forHTTPHeaderField:@"Range"]; 104 | } else { 105 | [fileManager removeItemAtPath:_filename error:nil]; 106 | [fileManager createFileAtPath:_filename contents:nil attributes:nil]; 107 | } 108 | } else { 109 | // Just create a new file 110 | [fileManager createFileAtPath:_filename contents:nil attributes:nil]; 111 | } 112 | 113 | _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 114 | } 115 | 116 | - (void)cancel { 117 | [_connection cancel]; 118 | _connection = nil; 119 | } 120 | 121 | 122 | #pragma mark - 123 | 124 | - (void)failWithError:(NSError*)error { 125 | if (_handler) { 126 | _handler(nil, _response, error); 127 | } 128 | } 129 | 130 | - (void)finish { 131 | if (_handler) { 132 | _handler(_filename, _response, nil); 133 | } 134 | } 135 | 136 | 137 | #pragma mark - NSURLConnectionDelegate 138 | 139 | - (void)connection:(NSURLConnection*)aConnection didReceiveResponse:(NSURLResponse*)inResponse { 140 | _expectedContentLength = [inResponse expectedContentLength]; 141 | _downloadedLength = 0; 142 | 143 | _responseFileHandle = nil; 144 | 145 | if ([inResponse isKindOfClass:[NSHTTPURLResponse class]]) { 146 | _response = (NSHTTPURLResponse*)inResponse; 147 | 148 | NSInteger statusCode = [_response statusCode]; 149 | if (statusCode >= 200 && statusCode <= 299) { 150 | _responseFileHandle = [NSFileHandle fileHandleForWritingAtPath:_filename]; 151 | 152 | NSString *contentRangeHeader = [[_response allHeaderFields] objectForKey:@"Content-Range"]; 153 | NSString *removePrefix = [contentRangeHeader stringByReplacingOccurrencesOfString:@"bytes " withString:@""]; 154 | NSArray *splitSlash = [removePrefix componentsSeparatedByString:@"/"]; 155 | if (splitSlash.count == 2) { 156 | NSArray *splitDash = [[splitSlash objectAtIndex:0] componentsSeparatedByString:@"-"]; 157 | if (splitDash.count == 2) { 158 | NSString *startByte = [splitDash objectAtIndex:0]; 159 | unsigned long long bytes = strtoull([startByte UTF8String], NULL, 0); 160 | @try { 161 | [_responseFileHandle seekToFileOffset:bytes]; 162 | _expectedContentLength += bytes; 163 | _downloadedLength += bytes; 164 | } @catch (NSException *e) { 165 | [_connection cancel]; 166 | _connection = nil; 167 | [self failWithError:nil]; 168 | } 169 | } 170 | } 171 | } else if (statusCode == 416) { 172 | [_connection cancel]; 173 | _connection = nil; 174 | NSFileManager *fileManager = [[NSFileManager alloc] init]; 175 | [fileManager removeItemAtPath:_filename error:nil]; 176 | [self startWithHandler:_handler progressHandler:_progressHandler]; 177 | } else { 178 | [_connection cancel]; 179 | _connection = nil; 180 | NSError *error = [NSError errorWithDomain:NSURLErrorDomain 181 | code:NSURLErrorUnknown 182 | userInfo:nil]; 183 | [self failWithError:error]; 184 | } 185 | } 186 | } 187 | 188 | - (NSURLRequest *)connection:(NSURLConnection *)aConnection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse { 189 | return nil; 190 | } 191 | 192 | - (void)connection:(NSURLConnection*)aConnection didReceiveData:(NSData*)data { 193 | _downloadedLength += [data length]; 194 | 195 | if (_responseFileHandle) { 196 | [_responseFileHandle writeData:data]; 197 | [_responseFileHandle synchronizeFile]; 198 | } 199 | 200 | if (_expectedContentLength != NSURLResponseUnknownLength) { 201 | if (_progressHandler) { 202 | _progressHandler([self progress]); 203 | } 204 | } 205 | } 206 | 207 | - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { 208 | } 209 | 210 | - (NSCachedURLResponse*)connection:(NSURLConnection*)aConnection willCacheResponse:(NSCachedURLResponse*)cachedResponse { 211 | return nil; 212 | } 213 | 214 | - (void)connectionDidFinishLoading:(NSURLConnection*)aConnection { 215 | [self finish]; 216 | _responseFileHandle = nil; 217 | _connection = nil; 218 | } 219 | 220 | - (void)connection:(NSURLConnection*)aConnection didFailWithError:(NSError*)error { 221 | [self failWithError:error]; 222 | _responseFileHandle = nil; 223 | _connection = nil; 224 | } 225 | 226 | 227 | #pragma mark - 228 | 229 | - (id)init { 230 | if ((self = [super init])) { 231 | _expectedContentLength = NSURLResponseUnknownLength; 232 | _downloadedLength = 0; 233 | } 234 | return self; 235 | } 236 | 237 | - (void)dealloc { 238 | [_connection cancel]; 239 | } 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /Source/MJGHTTPRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJGHTTPRequest.h 3 | // MJGHTTPRequest 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | typedef enum { 32 | MJGHTTPRequestMethodGET = 1, 33 | MJGHTTPRequestMethodPOST, 34 | } MJGHTTPRequestMethod; 35 | 36 | typedef enum { 37 | MJGHTTPRequestMethodPOSTFormatRawData = 1, 38 | MJGHTTPRequestMethodPOSTFormatURLEncode, 39 | MJGHTTPRequestMethodPOSTFormatFormData, 40 | } MJGHTTPRequestPOSTFormat; 41 | 42 | typedef void(^MJGHTTPRequestHandler)(id result, NSHTTPURLResponse *response, NSError *error); 43 | typedef void(^MJGHTTPRequestProgressHandler)(BOOL uploading, float progress); 44 | 45 | @class MJGHTTPRequest; 46 | 47 | @interface MJGHTTPRequest : NSObject 48 | 49 | @property (nonatomic, strong) NSDictionary *parameters; 50 | @property (nonatomic, assign) MJGHTTPRequestPOSTFormat postFormat; 51 | 52 | - (id)initWithRequestMethod:(MJGHTTPRequestMethod)method; 53 | + (MJGHTTPRequest*)requestWithRequestMethod:(MJGHTTPRequestMethod)method; 54 | 55 | - (void)setPOSTBody:(NSData*)data type:(NSString*)type; 56 | - (void)addFileData:(NSData*)data forKey:(NSString*)key withFilename:(NSString*)filename type:(NSString*)type; 57 | 58 | - (void)startWithHandler:(MJGHTTPRequestHandler)handler; 59 | - (void)startWithHandler:(MJGHTTPRequestHandler)handler progressHandler:(MJGHTTPRequestProgressHandler)progressHandler; 60 | - (void)cancel; 61 | 62 | /** 63 | * IMPORTANT: Must override this method! 64 | * Return the URL to hit for this request. 65 | */ 66 | - (NSString*)url; 67 | 68 | /** 69 | * Return any extra paramters to add to the request. 70 | */ 71 | - (NSDictionary*)extraParameters; 72 | 73 | /** 74 | * Return any extra GET query paramters to add to the request. 75 | * This can be used to always have certain parameters in the query part of the URL. 76 | */ 77 | - (NSDictionary*)extraGetParameters; 78 | 79 | /** 80 | * Optionally override this to handle the data which has been returned from the request. 81 | * If error is set by this method then it is passed back to the handler. 82 | * An example implementation for this would be to deserialise a JSON body. 83 | */ 84 | - (id)handleResult:(NSData*)result error:(NSError**)error; 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Source/MJGHTTPRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJGHTTPRequest.m 3 | // MJGHTTPRequest 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #if ! __has_feature(objc_arc) 30 | #error This file requires ARC to be enabled. Either enable ARC for the entire project or use -fobjc-arc flag. 31 | #endif 32 | 33 | #import "MJGHTTPRequest.h" 34 | 35 | #import "NSDictionary-HTTP.h" 36 | 37 | @interface MJGHTTPRequest () 38 | @property (nonatomic, assign) MJGHTTPRequestMethod method; 39 | @property (nonatomic, strong) NSData *rawPostData; 40 | @property (nonatomic, copy) NSString *rawPostType; 41 | @property (nonatomic, strong) NSMutableArray *fileData; 42 | 43 | @property (nonatomic, copy) MJGHTTPRequestHandler handler; 44 | @property (nonatomic, copy) MJGHTTPRequestProgressHandler progressHandler; 45 | 46 | @property (nonatomic, strong) NSURLConnection *connection; 47 | @property (nonatomic, strong) NSHTTPURLResponse *response; 48 | @property (nonatomic, strong) NSMutableData *responseData; 49 | @property (nonatomic, assign) long long expectedContentLength; 50 | @property (nonatomic, assign) long long downloadedLength; 51 | 52 | - (void)failWithError:(NSError*)error; 53 | - (void)handleResponseData; 54 | 55 | - (void)generateFormDataPostBody:(NSMutableURLRequest*)request; 56 | - (void)generateUrlEncodedPostBody:(NSMutableURLRequest*)request; 57 | @end 58 | 59 | @implementation MJGHTTPRequest 60 | 61 | @synthesize parameters = _parameters, postFormat = _postFormat; 62 | @synthesize method = _method, rawPostData = _rawPostData, rawPostType = _rawPostType, fileData = _fileData; 63 | @synthesize handler = _handler, progressHandler = _progressHandler; 64 | @synthesize connection = _connection, response = _response, responseData = _responseData, expectedContentLength = _expectedContentLength, downloadedLength = _downloadedLength; 65 | 66 | #pragma mark - 67 | 68 | - (id)initWithRequestMethod:(MJGHTTPRequestMethod)inMethod { 69 | if ((self = [self init])) { 70 | _method = inMethod; 71 | _postFormat = MJGHTTPRequestMethodPOSTFormatURLEncode; 72 | } 73 | return self; 74 | } 75 | 76 | + (MJGHTTPRequest*)requestWithRequestMethod:(MJGHTTPRequestMethod)method { 77 | return [[MJGHTTPRequest alloc] initWithRequestMethod:method]; 78 | } 79 | 80 | 81 | #pragma mark - 82 | 83 | - (void)setPOSTBody:(NSData*)data type:(NSString*)type { 84 | // We need to set the post method to raw data if we're setting the post body 85 | _postFormat = MJGHTTPRequestMethodPOSTFormatRawData; 86 | _rawPostData = data; 87 | _rawPostType = type; 88 | } 89 | 90 | - (void)addFileData:(NSData*)data forKey:(NSString*)key withFilename:(NSString*)filename type:(NSString*)type { 91 | // We need to set the post method to form data if we're adding files 92 | _postFormat = MJGHTTPRequestMethodPOSTFormatFormData; 93 | 94 | NSDictionary *newFileData = [NSDictionary dictionaryWithObjectsAndKeys: 95 | data, @"data", 96 | key, @"key", 97 | filename, @"filename", 98 | type, @"type", 99 | nil]; 100 | [_fileData addObject:newFileData]; 101 | } 102 | 103 | - (void)startWithHandler:(MJGHTTPRequestHandler)inHandler { 104 | [self startWithHandler:inHandler progressHandler:nil]; 105 | } 106 | 107 | - (void)startWithHandler:(MJGHTTPRequestHandler)inHandler progressHandler:(MJGHTTPRequestProgressHandler)inProgressHandler { 108 | self.handler = inHandler; 109 | self.progressHandler = inProgressHandler; 110 | 111 | NSMutableString *url = [NSMutableString stringWithString:[self url]]; 112 | 113 | NSMutableDictionary *allGetParameters = [NSMutableDictionary dictionaryWithCapacity:0]; 114 | [allGetParameters addEntriesFromDictionary:[self extraGetParameters]]; 115 | 116 | if (_method == MJGHTTPRequestMethodGET) { 117 | [allGetParameters addEntriesFromDictionary:[self extraParameters]]; 118 | [allGetParameters addEntriesFromDictionary:_parameters]; 119 | } 120 | 121 | if (allGetParameters.count > 0) { 122 | [url appendFormat:@"?%@", [allGetParameters getQuery]]; 123 | } 124 | 125 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url] 126 | cachePolicy:NSURLRequestReloadIgnoringLocalCacheData 127 | timeoutInterval:30.0]; 128 | 129 | if (_method == MJGHTTPRequestMethodGET) { 130 | [request setHTTPMethod:@"GET"]; 131 | } else if (_method == MJGHTTPRequestMethodPOST) { 132 | [request setHTTPMethod:@"POST"]; 133 | if (_postFormat == MJGHTTPRequestMethodPOSTFormatRawData) { 134 | [request setHTTPBody:_rawPostData]; 135 | if (_rawPostType) { 136 | [request setValue:_rawPostType forHTTPHeaderField:@"Content-Type"]; 137 | } 138 | } else if (_postFormat == MJGHTTPRequestMethodPOSTFormatFormData) { 139 | [self generateFormDataPostBody:request]; 140 | } else if (_postFormat == MJGHTTPRequestMethodPOSTFormatURLEncode) { 141 | [self generateUrlEncodedPostBody:request]; 142 | } 143 | } 144 | 145 | _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; 146 | } 147 | 148 | - (void)cancel { 149 | [_connection cancel]; 150 | _connection = nil; 151 | } 152 | 153 | 154 | #pragma mark - 155 | 156 | - (void)failWithError:(NSError*)error { 157 | if (_handler) { 158 | _handler(nil, _response, error); 159 | } 160 | } 161 | 162 | - (void)handleResponseData { 163 | NSError *error = nil; 164 | id result = [self handleResult:_responseData error:&error]; 165 | if (_handler) { 166 | _handler(result, _response, error); 167 | } 168 | _responseData = nil; 169 | } 170 | 171 | 172 | #pragma mark - POST body generation 173 | 174 | - (void)generateFormDataPostBody:(NSMutableURLRequest*)request { 175 | NSString *httpBoundary = @"----MJGHTTPRequest0xce86d7d02a229acfaca4b63f01a1171b"; 176 | 177 | [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", httpBoundary] forHTTPHeaderField:@"Content-Type"]; 178 | 179 | NSMutableData *body = [[NSMutableData alloc] init]; 180 | 181 | NSString *startLine = [NSString stringWithFormat:@"\r\n"]; 182 | NSString *endLine = [NSString stringWithFormat:@"\r\n--%@", httpBoundary]; 183 | 184 | [body appendData:[[NSString stringWithFormat:@"--%@", httpBoundary] dataUsingEncoding:NSUTF8StringEncoding]]; 185 | 186 | NSMutableDictionary *allParameters = [NSMutableDictionary dictionaryWithDictionary:_parameters]; 187 | [allParameters addEntriesFromDictionary:[self extraParameters]]; 188 | 189 | for (id key in [allParameters keyEnumerator]) { 190 | id value = [allParameters objectForKey:key]; 191 | if ([value isKindOfClass:[NSString class]]) { 192 | [body appendData:[startLine dataUsingEncoding:NSUTF8StringEncoding]]; 193 | [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]]; 194 | [body appendData:[@"Content-Type: text/plain; charset=utf-8\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 195 | [body appendData:[(NSString*)value dataUsingEncoding:NSUTF8StringEncoding]]; 196 | [body appendData:[endLine dataUsingEncoding:NSUTF8StringEncoding]]; 197 | } else if ([value isKindOfClass:[NSNumber class]]) { 198 | [body appendData:[startLine dataUsingEncoding:NSUTF8StringEncoding]]; 199 | [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]]; 200 | [body appendData:[@"Content-Type: text/plain; charset=utf-8\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 201 | [body appendData:[[(NSNumber*)value stringValue] dataUsingEncoding:NSUTF8StringEncoding]]; 202 | [body appendData:[endLine dataUsingEncoding:NSUTF8StringEncoding]]; 203 | } 204 | } 205 | 206 | for (NSDictionary *dict in _fileData) { 207 | NSData *data = [dict objectForKey:@"data"]; 208 | NSData *key = [dict objectForKey:@"key"]; 209 | NSData *filename = [dict objectForKey:@"filename"]; 210 | NSData *type = [dict objectForKey:@"type"]; 211 | 212 | [body appendData:[startLine dataUsingEncoding:NSUTF8StringEncoding]]; 213 | 214 | [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", key, filename] dataUsingEncoding:NSUTF8StringEncoding]]; 215 | [body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", type] dataUsingEncoding:NSUTF8StringEncoding]]; 216 | [body appendData:data]; 217 | 218 | [body appendData:[endLine dataUsingEncoding:NSUTF8StringEncoding]]; 219 | } 220 | 221 | [body appendData:[@"--\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 222 | 223 | [request setHTTPBody:body]; 224 | } 225 | 226 | - (void)generateUrlEncodedPostBody:(NSMutableURLRequest*)request { 227 | NSMutableDictionary *allParameters = [NSMutableDictionary dictionaryWithDictionary:_parameters]; 228 | [allParameters addEntriesFromDictionary:[self extraParameters]]; 229 | 230 | NSData *thisPostData = [allParameters formEncodedPostData]; 231 | [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 232 | [request setHTTPBody:thisPostData]; 233 | } 234 | 235 | 236 | #pragma mark - NSURLConnectionDelegate 237 | 238 | - (void)connection:(NSURLConnection*)aConnection didReceiveResponse:(NSURLResponse*)inResponse { 239 | _responseData = [[NSMutableData alloc] init]; 240 | _expectedContentLength = [inResponse expectedContentLength]; 241 | _downloadedLength = 0; 242 | 243 | if ([inResponse isKindOfClass:[NSHTTPURLResponse class]]) { 244 | _response = (NSHTTPURLResponse*)inResponse; 245 | } 246 | } 247 | 248 | - (void)connection:(NSURLConnection*)aConnection didReceiveData:(NSData*)data { 249 | _downloadedLength += [data length]; 250 | 251 | [_responseData appendData:data]; 252 | 253 | if (_expectedContentLength != NSURLResponseUnknownLength) { 254 | if (_progressHandler) { 255 | float p = (float)_downloadedLength / (float)_expectedContentLength; 256 | _progressHandler(NO, p); 257 | } 258 | } 259 | } 260 | 261 | - (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite { 262 | if (_progressHandler) { 263 | float p = (float)totalBytesWritten / (float)totalBytesExpectedToWrite; 264 | _progressHandler(YES, p); 265 | } 266 | } 267 | 268 | - (void)connectionDidFinishLoading:(NSURLConnection*)aConnection { 269 | [self handleResponseData]; 270 | _responseData = nil; 271 | _connection = nil; 272 | } 273 | 274 | - (void)connection:(NSURLConnection*)aConnection didFailWithError:(NSError*)error { 275 | [self failWithError:error]; 276 | _responseData = nil; 277 | _connection = nil; 278 | } 279 | 280 | 281 | #pragma mark - Default methods 282 | 283 | - (NSString*)url { 284 | @throw [NSException exceptionWithName:NSInternalInconsistencyException 285 | reason:[NSString stringWithFormat:@"Subclasses must override %@.", NSStringFromSelector(_cmd)] 286 | userInfo:nil]; 287 | } 288 | 289 | - (NSDictionary*)extraParameters { 290 | return nil; 291 | } 292 | 293 | - (NSDictionary*)extraGetParameters { 294 | return nil; 295 | } 296 | 297 | - (id)handleResult:(NSData*)result error:(NSError**)error { 298 | return result; 299 | } 300 | 301 | 302 | #pragma mark - 303 | 304 | - (id)init { 305 | if ((self = [super init])) { 306 | _expectedContentLength = NSURLResponseUnknownLength; 307 | _downloadedLength = 0; 308 | 309 | _fileData = [[NSMutableArray alloc] initWithCapacity:0]; 310 | } 311 | return self; 312 | } 313 | 314 | @end 315 | -------------------------------------------------------------------------------- /Source/NSDictionary-HTTP.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary-HTTP.h 3 | // MJGHTTPRequest 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | @interface NSDictionary (HTTP) 32 | 33 | - (NSString*)getQuery; 34 | - (NSData*)formEncodedPostData; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Source/NSDictionary-HTTP.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary-HTTP.m 3 | // MJGHTTPRequest 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #if ! __has_feature(objc_arc) 30 | #error This file requires ARC to be enabled. Either enable ARC for the entire project or use -fobjc-arc flag. 31 | #endif 32 | 33 | #import "NSDictionary-HTTP.h" 34 | 35 | #import "NSString-HTTP.h" 36 | 37 | @implementation NSDictionary (HTTP) 38 | 39 | - (NSString*)getQuery { 40 | NSMutableArray *pairs = [[NSMutableArray alloc] initWithCapacity:0]; 41 | for (NSString *key in [self keyEnumerator]) { 42 | id value = [self objectForKey:key]; 43 | 44 | // TODO: Support more than just NSString and NSNumber 45 | 46 | if ([value isKindOfClass:[NSString class]]) { 47 | [pairs addObject:[NSString stringWithFormat:@"%@=%@", 48 | [key urlEncodedString], 49 | [(NSString*)value urlEncodedString]]]; 50 | } else if ([value isKindOfClass:[NSNumber class]]) { 51 | [pairs addObject:[NSString stringWithFormat:@"%@=%@", 52 | [key urlEncodedString], 53 | [[(NSNumber*)value stringValue] urlEncodedString]]]; 54 | } 55 | } 56 | return [pairs componentsJoinedByString:@"&"]; 57 | } 58 | 59 | - (NSData*)formEncodedPostData { 60 | return [[self getQuery] dataUsingEncoding:NSUTF8StringEncoding]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Source/NSString-HTTP.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString-HTTP.h 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #import 30 | 31 | @interface NSString (HTTP) 32 | 33 | - (NSString*)urlEncodedString; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Source/NSString-HTTP.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString-HTTP.m 3 | // MJGHTTPRequestDemo 4 | // 5 | // Copyright (c) 2011 Matt Galloway. All rights reserved. 6 | // 7 | // Redistribution and use in source and binary forms, with or without 8 | // modification, are permitted provided that the following conditions are met: 9 | // 10 | // 1. Redistributions of source code must retain the above copyright notice, this 11 | // list of conditions and the following disclaimer. 12 | // 13 | // 2. Redistributions in binary form must reproduce the above copyright notice, 14 | // this list of conditions and the following disclaimer in the documentation 15 | // and/or other materials provided with the distribution. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | // 28 | 29 | #if ! __has_feature(objc_arc) 30 | #error This file requires ARC to be enabled. Either enable ARC for the entire project or use -fobjc-arc flag. 31 | #endif 32 | 33 | #import "NSString-HTTP.h" 34 | 35 | @implementation NSString (HTTP) 36 | 37 | - (NSString*)urlEncodedString { 38 | NSString *encoded = (__bridge_transfer NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, 39 | (__bridge CFStringRef)self, 40 | NULL, 41 | (CFStringRef)@"!*'();:@&=+$,/?%#[]", 42 | kCFStringEncodingUTF8); 43 | return encoded; 44 | } 45 | 46 | @end 47 | --------------------------------------------------------------------------------