Skip to content

Commit

Permalink
Import MicroHTTPKit and write Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hmelder committed Jan 11, 2024
1 parent 6cb3ce5 commit 5a3ed2f
Show file tree
Hide file tree
Showing 18 changed files with 1,105 additions and 0 deletions.
16 changes: 16 additions & 0 deletions Libraries/MicroHTTPKit/MicroHTTPKit/HKHTTPConstants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <Foundation/NSString.h>

extern NSString *const HKHTTPMethodGET;
extern NSString *const HKHTTPMethodHEAD;
extern NSString *const HKHTTPMethodOptions;
extern NSString *const HKHTTPMethodPOST;
extern NSString *const HKHTTPMethodPUT;

extern NSString *const HKHTTPHeaderContentType;
extern NSString *const HKHTTPHeaderContentApplicationJSON;
43 changes: 43 additions & 0 deletions Libraries/MicroHTTPKit/MicroHTTPKit/HKHTTPRequest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface HKHTTPRequest : NSObject {
@private
NSData *_HTTPBody;
}

@property (readonly, copy) NSString *method;
@property (readonly, copy) NSURL *URL;
@property (readonly, copy) NSDictionary<NSString *, NSString *> *headers;
@property (readonly, copy) NSDictionary<NSString *, NSString *> *queryParameters;

/**
* @brief The user info dictionary for the request.
*
* This property is initialized to an empty dictionary, which you can then use to store
* app-specific information. For example, you might use it during the processing of the
* request to store processing-related data in the middleware.
*/
@property (copy) NSDictionary *userInfo;

- (instancetype)initWithMethod:(NSString *)method
URL:(NSURL *)URL
headers:(NSDictionary<NSString *, NSString *> *)headers;

- (instancetype)initWithMethod:(NSString *)method
URL:(NSURL *)URL
headers:(NSDictionary<NSString *, NSString *> *)headers
queryParameters:(NSDictionary<NSString *, NSString *> *)queryParameters;

- (NSData *)HTTPBody;

@end

NS_ASSUME_NONNULL_END
40 changes: 40 additions & 0 deletions Libraries/MicroHTTPKit/MicroHTTPKit/HKHTTPResponse.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface HKHTTPResponse : NSObject

@property (strong, nullable) NSData *data;
@property (assign) NSUInteger status;
@property (strong) NSDictionary<NSString *, NSString *> *headers;

+ (instancetype)responseWithStatus:(NSUInteger)status;
+ (instancetype)responseWithData:(NSData *)data status:(NSUInteger)status;

- (instancetype)initWithStatus:(NSUInteger)status;

- (instancetype)initWithData:(NSData *)data status:(NSUInteger)status;

- (instancetype)initWithData:(NSData *)data
headers:(NSDictionary<NSString *, NSString *> *)headers
status:(NSUInteger)status;

@end

@interface HKHTTPJSONResponse : HKHTTPResponse

+ (instancetype)responseWithJSONObject:(id)JSONObject
status:(NSUInteger)status
error:(NSError **)error;

- (instancetype)initWithJSONObject:(id)JSONObject status:(NSUInteger)status error:(NSError **)error;

@end

NS_ASSUME_NONNULL_END
27 changes: 27 additions & 0 deletions Libraries/MicroHTTPKit/MicroHTTPKit/HKHTTPServer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <Foundation/Foundation.h>

#import <MicroHTTPKit/HKRouter.h>

NS_ASSUME_NONNULL_BEGIN

@interface HKHTTPServer : NSObject

@property (nonatomic, readonly) NSUInteger port;
@property (readonly) HKRouter *router;

+ (instancetype)serverWithPort:(NSUInteger)port;

- (instancetype)initWithPort:(NSUInteger)port;

- (BOOL)startWithError:(NSError **)error;
- (void)stop;

@end

NS_ASSUME_NONNULL_END
64 changes: 64 additions & 0 deletions Libraries/MicroHTTPKit/MicroHTTPKit/HKRouter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <Foundation/Foundation.h>
#include <Foundation/NSObjCRuntime.h>

#import <MicroHTTPKit/HKHTTPRequest.h>
#import <MicroHTTPKit/HKHTTPResponse.h>

NS_ASSUME_NONNULL_BEGIN

typedef HKHTTPResponse *_Nonnull (^HKHandlerBlock)(HKHTTPRequest *request);

extern NSString *const HKResponseDataKey;
extern NSString *const HKResponseStatusKey;

@interface HKRoute : NSObject

@property (readonly, copy) NSString *path;
@property (readonly, copy) HKHandlerBlock handler;
@property (readonly, copy) NSString *method;

+ (instancetype)routeWithPath:(NSString *)path
method:(NSString *)method
handler:(HKHandlerBlock)handler;

- (instancetype)initWithPath:(NSString *)path
method:(NSString *)method
handler:(HKHandlerBlock)handler;

@end

@interface HKRouter : NSObject

@property (copy) HKHandlerBlock notFoundHandler;

/**
* A middleware block that is called before the handler block.
* The middleware block can be used to modify the userInfo dictionary in the request before it is
* handled.
*
* If the middleware block returns a HKHTTPResponse object, this response is used instead of
* calling the handler block.
*/
@property (copy, nullable) HKHandlerBlock middleware;

- (HKHandlerBlock)handlerForRequest:(HKHTTPRequest *)request;

+ (instancetype)routerWithRoutes:(NSArray<HKRoute *> *)routes
notFoundHandler:(HKHandlerBlock)notFoundHandler;

- (instancetype)initWithRoutes:(NSArray<HKRoute *> *)routes
notFoundHandler:(HKHandlerBlock)notFoundHandler NS_DESIGNATED_INITIALIZER;

- (void)registerRoute:(HKRoute *)route;

- (NSArray<HKRoute *> *)routes;

@end

NS_ASSUME_NONNULL_END
11 changes: 11 additions & 0 deletions Libraries/MicroHTTPKit/MicroHTTPKit/MicroHTTPKit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <MicroHTTPKit/HKHTTPConstants.h>
#import <MicroHTTPKit/HKHTTPRequest.h>
#import <MicroHTTPKit/HKHTTPResponse.h>
#import <MicroHTTPKit/HKHTTPServer.h>
#import <MicroHTTPKit/HKRouter.h>
16 changes: 16 additions & 0 deletions Libraries/MicroHTTPKit/Source/HKHTTPConstants.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <MicroHTTPKit/HKHTTPConstants.h>

NSString *const HKHTTPMethodGET = @"GET";
NSString *const HKHTTPMethodHEAD = @"HEAD";
NSString *const HKHTTPMethodOptions = @"OPTIONS";
NSString *const HKHTTPMethodPOST = @"POST";
NSString *const HKHTTPMethodPUT = @"PUT";

NSString *const HKHTTPHeaderContentType = @"Content-Type";
NSString *const HKHTTPHeaderContentApplicationJSON = @"application/json";
13 changes: 13 additions & 0 deletions Libraries/MicroHTTPKit/Source/HKHTTPRequest+Private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <MicroHTTPKit/HKHTTPRequest.h>

@interface HKHTTPRequest (Private)

- (void)appendBytesToHTTPBody:(const void *)bytes length:(NSUInteger)length;

@end
18 changes: 18 additions & 0 deletions Libraries/MicroHTTPKit/Source/HKHTTPRequest+Private.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import "HKHTTPRequest+Private.h"

@implementation HKHTTPRequest (Private)

- (void)appendBytesToHTTPBody:(const void *)bytes length:(NSUInteger)length {
NSAssert([_HTTPBody isKindOfClass:[NSMutableData class]], @"HTTPBody is not mutable", nil);

NSMutableData *data = (NSMutableData *) _HTTPBody;
[data appendBytes:bytes length:length];
}

@end
50 changes: 50 additions & 0 deletions Libraries/MicroHTTPKit/Source/HKHTTPRequest.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <MicroHTTPKit/HKHTTPRequest.h>

@implementation HKHTTPRequest

- (instancetype)initWithMethod:(NSString *)method
URL:(NSURL *)URL
headers:(NSDictionary<NSString *, NSString *> *)headers {
return [self initWithMethod:method URL:URL headers:headers HTTPBody:nil];
}

// If we don't pass a HTTPBody in the initialiser, we assume that we will append data later on.
// We thus create a mutable data object.
- (instancetype)initWithMethod:(NSString *)method
URL:(NSURL *)URL
headers:(NSDictionary<NSString *, NSString *> *)headers
queryParameters:(NSDictionary<NSString *, NSString *> *)queryParameters {
self = [self initWithMethod:method URL:URL headers:headers];
if (self) {
_queryParameters = [queryParameters copy];
_HTTPBody = [NSMutableData data];
}
return self;
}

- (instancetype)initWithMethod:(NSString *)method
URL:(NSURL *)URL
headers:(NSDictionary<NSString *, NSString *> *)headers
HTTPBody:(nullable NSData *)HTTPBody {
self = [super init];
if (self) {
_method = [method copy];
_URL = [URL copy];
_headers = [headers copy];
_HTTPBody = [HTTPBody copy];
_userInfo = @{};
}
return self;
}

- (NSData *)HTTPBody {
return [_HTTPBody copy];
}

@end
68 changes: 68 additions & 0 deletions Libraries/MicroHTTPKit/Source/HKHTTPResponse.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/* MicroHTTPKit - A small libmicrohttpd wrapper
* Copyright (C) 2023 Hugo Melder
*
* SPDX-License-Identifier: MIT
*/

#import <MicroHTTPKit/HKHTTPConstants.h>
#import <MicroHTTPKit/HKHTTPResponse.h>

@implementation HKHTTPResponse

+ (instancetype)responseWithStatus:(NSUInteger)status {
return [[self alloc] initWithStatus:status];
}

+ (instancetype)responseWithData:(NSData *)data status:(NSUInteger)status {
return [[self alloc] initWithData:data status:status];
}

- (instancetype)initWithStatus:(NSUInteger)status {
self = [super init];

if (self) {
_status = status;
}

return self;
}

- (instancetype)initWithData:(NSData *)data status:(NSUInteger)status {
return [self initWithData:data headers:@{} status:status];
}

- (instancetype)initWithData:(NSData *)data
headers:(NSDictionary<NSString *, NSString *> *)headers
status:(NSUInteger)status {
self = [super init];
if (self) {
_data = data;
_headers = headers;
_status = status;
}
return self;
}

@end

@implementation HKHTTPJSONResponse

+ (instancetype)responseWithJSONObject:(id)JSONObject
status:(NSUInteger)status
error:(NSError **)error {
return [[self alloc] initWithJSONObject:JSONObject status:status error:error];
}

- (instancetype)initWithJSONObject:(id)JSONObject
status:(NSUInteger)status
error:(NSError **)error {
NSData *data;
NSDictionary *headers;

headers = @{HKHTTPHeaderContentType : HKHTTPHeaderContentApplicationJSON};
data = [NSJSONSerialization dataWithJSONObject:JSONObject options:0 error:error];

return [self initWithData:data headers:headers status:status];
}

@end
Loading

0 comments on commit 5a3ed2f

Please sign in to comment.