swisspol / gcdwebserver Goto Github PK
View Code? Open in Web Editor NEWThe #1 HTTP server for iOS, macOS & tvOS (also includes web based uploader & WebDAV server)
License: Other
The #1 HTTP server for iOS, macOS & tvOS (also includes web based uploader & WebDAV server)
License: Other
I'm trying to use GCDWebUploader on an iOS 8 only project using CocoaPods.
My code is as follows (on a View Controller):
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
self.server = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
self.server.allowHiddenItems = YES;
self.server.delegate = self;
[self.server start];
}
The server starts, and I get
[INFO] GCDWebUploader started on port 8080 and reachable at http://192.168.1.111:8080/
on the console. However, as soon as I load the page, I get a blank page and this error is logged:
[EXCEPTION] *** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[1]
Any idea? Weirdly enough, if I run the project with pod try
it works fine, and also if I clone it from Github and run the demo.
Some times when on WiFi network, starting the Web Server I get this log
[INFO] GCDWebServer now reachable at (null)
Apparently it seems that I do not have any ip address.
In this case which of these delegates is called?
- (void)webServerDidStart:(GCDWebServer*)server {
}
- (void)webServerDidConnect:(GCDWebServer*)server {
}
- (void)webServerDidDisconnect:(GCDWebServer*)server {
}
- (void)webServerDidStop:(GCDWebServer*)server {
}
In
how to replace dispatch_get_current_queue() since its deprecated ?
Hi,
Is it possible to get file transfer progress feedback from the sever?
regards.
ok, so i subclassed the GCDWebServerConnection, and overrode the
(void)didWriteBytes:(const void*)bytes length:(NSUInteger)length{
[[NSNotificationCenter defaultCenter] postNotificationName:SERVER_ASSET_UPLOAD_PROGRESS object:self userInfo:dict];
[super didWriteBytes:bytes length:length];
}
nothing else. and call
[self.server startWithOptions: @{GCDWebServerOption_ConnectionClass:NSStringFromClass([MYGCDWebServerConnection class])} error:&error];
I receive no errors ,but when the first request comes in, The app crashes with
2014-07-25 14:57:30.119 FlyBy[86947:1303] -[NSCFString alloc]: unrecognized selector sent to instance 0xa384850
2014-07-25 14:57:30.861 FlyBy[86947:1303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString alloc]: unrecognized selector sent to instance 0xa384850'
*** First throw call stack:
(
0 CoreFoundation 0x026861e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x024058e5 objc_exception_throw + 44
2 CoreFoundation 0x02723243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x0267650b __forwarding + 1019
4 CoreFoundation 0x026760ee _CF_forwarding_prep_0 + 14
5 FlyBy 0x0011dfab __23-[GCDWebServer _start:]_block_invoke156 + 395
6 libdispatch.dylib 0x0299e4d0 _dispatch_client_callout + 14
7 libdispatch.dylib 0x02994e93 _dispatch_source_latch_and_call + 150
8 libdispatch.dylib 0x0298f43f _dispatch_source_invoke + 415
9 libdispatch.dylib 0x0298cde2 _dispatch_root_queue_drain + 78
10 libdispatch.dylib 0x0298d127 _dispatch_worker_thread2 + 39
11 libsystem_pthread.dylib 0x02ccddab _pthread_wqthread + 336
12 libsystem_pthread.dylib 0x02cd1cce start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type NSException
if i remove the option, and just call start, everything works fine.
but then i dont receive the notifications i've aded to my custom class.
will a 64 bit version be available ?
Does it possible to run server without wifi connection (and 3G/LTE)?
For example, when current device is the only one client for this server. When i tried to use GCDAsyncSocket, accept() function creates listening server at 0.0.0.0:port.
I mean, for PC version it is normal to use localhost. But, i guess for iPhone/iPad it is not possible. Am i right?
Thank you.
Hi,
When server request is mp4 files, I want to response changed other mp4 from NSdata formatted. I research many times. But I haven't solve problem. How can I use GCDWebServerStreamedResponse class?. Please help me?
I get a broken pipe error when sending an 11MB mp4 file through the socket
If I install GCDWebServer via CocoaPods I only get the "Core" and the "Support Files" folder. The "Requests" and the "Responses" folders are missing :-(
Did I something wrong?
Ralph
Summary: GCDWebUploader
does nothing to prevent uploading and deleting files outside of uploadDirectory
. This can be accomplished by using ..
path components in the path
parameter in a POST /upload
or POST /delete
.
Expected Behavior: Attempting to upload or delete a file outside of uploadDirectory
will fail.
Actual Behavior: Attempting to upload or delete a file outside of uploadDirectory
succeeds.
Notes: It isn't entirely clear whether this behavior is desired or not. I wanted to disable it, so I check the path in the appropriate -*should
methods in a GCDWebUploader subclass.
Hi Pierre
If I directly open the server after start server, the mobile safari may not fetch the content sometimes, do you know how to detect the server is really ok? Did i need to delay open url?
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.backgroundColor = [UIColor whiteColor];
[_window makeKeyAndVisible];
_webServer = [[GCDWebServer alloc] init];
[_webServer addDefaultHandlerForMethod:@"GET"
requestClass:[GCDWebServerRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];
}];
[_webServer start];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://localhost:8080"]];
return YES;
}
I created a GCDWebserver instance and call start method. The start method returns true even without wifi connected !.
How to detect server Connected / Disconnected ?
Can't figure out how to build a Swift project using GCDWebserver in XCode 6.0 (bรจta).
Steps:
When building, I get the following error:
Undefined symbols for architecture x86_64:
"_deflate", referenced from:
-[GCDWebServerGZipEncoder readData:] in GCDWebServerResponse.o
"_deflateEnd", referenced from:
-[GCDWebServerGZipDecoder open:] in GCDWebServerRequest.o
-[GCDWebServerGZipEncoder open:] in GCDWebServerResponse.o
-[GCDWebServerGZipEncoder close] in GCDWebServerResponse.o
"_deflateInit2_", referenced from:
-[GCDWebServerGZipEncoder open:] in GCDWebServerResponse.o
"_inflate", referenced from:
-[GCDWebServerGZipDecoder writeData:error:] in GCDWebServerRequest.o
"_inflateEnd", referenced from:
-[GCDWebServerGZipDecoder close:] in GCDWebServerRequest.o
"_inflateInit2_", referenced from:
-[GCDWebServerGZipDecoder open:] in GCDWebServerRequest.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any ideas?
Changing the name to a custom one when publishing, the device become unreachable. Using the default one instead, the web server provide the content correctly.
Any suggestion?
How can I hide these ?
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
[DEBUG] Connection sent 32768 bytes on socket 15
Hi, thanks for the great work. I tried using the web server when off wifi, however the ip address shows null after launch. Is it possible to use it that way?
So here is the situation, I have a bunch of unit tests that are running with a dependency on GCDWebServer. Here is the ordering of events:
startWithOptions:
on the GCDWebServer property.webServerDidStart:
method.Here are some things I noticed:
serverURL
property returned by GCDWebServer.isRunning
property with an assert that it must be true. That test is also failing whenever this happens.Anyway what all this SEEMS to point to is that the delegate is receiving a callback before the server is ready to accept connections. I see the following potential solutions to this problem:
webServerDidCompleteBonjourRegistration:
to fire the notification event from the singleton and start the tests. This works but it slows down the tests by several orders of magnitude.isRunning
property test is failing I'm assuming it knows that the server is not ready for connections. As such I could use KVO on the isRunning
setter property Running
but since it looks like the getter is using the ivar _source
I suspect that the Running
property isn't really being used for setting the isRunning
state but I might try it and see or take a harder look at the code.Have you got any suggestions? The runWithOptions:
method mentions starting the server synchronously and I could use that instead of the delegate callback but the documentation isn't clear on what the blocking event is (I'll check the code but I imagine its something that might be good to clarify). I also don't see any other delegate callback methods that would work for this (or NSNotification constants) but maybe I'm missing something.
Would also fix compatibly issues with ARC host projects automatically.
Hi, I did a class extension of GCDWebServer and GCDWebServerConnection so that I could track the starting, ending and progress of data being sent to a client. I also had to add some code to the connection class:
[self willChangeValueForKey:@"totalBytesWritten"];
_bytesWritten += size;
[self didChangeValueForKey:@"totalBytesWritten"];
Which enabled the KVO tracking. Thought you might want to add this to the class - unless there is another way to do it :-)
GCDWebServer / GCDWebServer / Core / GCDWebServer.m (523-527)
NSTask* task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/opendiff"];
[task setArguments:@[expectedPath, actualPath]];
[task launch];
ARC_RELEASE(task);
Can't compile source files because of the NSTask which is not supported under iOS.
Btw, thank you. Mac-version works perfect.
We currently observe a crash in [GCDWebServer startWithOptions:error:]:620
that occurs because _options
are still set. We do check if the server is running before starting it, but the isRunning
method only check if _source
is set. Unfortunately I wasn't able to reproduce these crashes. It might be related to specific scenarios involving the background mode. Any hints on how this might be addressed?Is there a particular reason why it needs to abort in start if _options are set and abort in stop if not?
When I run this HTML file I eventually get a crash. The file is "video.html". It is just calling itself every 7 seconds. I am serving using GET
AppDelegate.m:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docRoot = [paths objectAtIndex:0];
_webServer = [[GCDWebServer alloc] init];
__weak typeof(GCDWebServer) *weakSelf = _webServer;
[_webServer addDefaultHandlerForMethod:@"GET"
requestClass:[GCDWebServerRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
NSString *filename = request.URL.lastPathComponent;
NSString *filePath = [NSString stringWithFormat:@"%@/%@",docRoot,filename];
GCDWebServerResponse *response;
NSLog(@"filename: %@",filename);
if ([filename isEqualToString:@"/"]) {
goto failed;
} else if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSRange range = request.byteRange;
if ((range.location != NSNotFound) || (range.length > 0)) {
response = [weakSelf _responseWithPartialContentsOfFile:filePath byteRange:range];
} else {
response = [weakSelf _responseWithContentsOfFile:filePath];
}
[response setValue:@"bytes" forAdditionalHeader:@"Accept-Ranges"];
return response;
}
failed:
NSLog(@"NOT EXIST: %@",filePath);
return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>File does not exist</p></body></html>"];
}];
[_webServer start];
ViewController.m:
self.webview.mediaPlaybackRequiresUserAction = NO;
[self.webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/video.html"]]];
video.html:
<html>
<head>
<script type="text/javascript">
setInterval(function(){document.location="video.html"},7000);
</script>
</head>
<body>
<video autoplay>
<source src="Fishmonger-Salmon_01_2.mp4" type="video/mp4">
</video>
</body>
</html>
Crash dump:
#0 0x3b56c626 in objc_msgSend ()
#1 0x313a8d5a in +[NSConcreteNotification newTempNotificationWithName:object:userInfo:] ()
#2 0x313a8cac in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#3 0x313ad5c6 in -[NSNotificationCenter postNotificationName:object:] ()
#4 0x31cf67bc in __53-[MPAVItem _playerItemNewAccessLogEntryNotification:]_block_invoke ()
#5 0x3ba4bd52 in _dispatch_call_block_and_release ()
#6 0x3ba4bd3e in _dispatch_client_callout ()
#7 0x3ba4e6c2 in _dispatch_main_queue_callback_4CF ()
#8 0x30a52678 in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#9 0x30a50f44 in __CFRunLoopRun ()
#10 0x309bb7a8 in CFRunLoopRunSpecific ()
#11 0x309bb58a in CFRunLoopRunInMode ()
#12 0x358f56d2 in GSEventRunModal ()
#13 0x3331a890 in UIApplicationMain ()
#14 0x000c29b4 in main at /Users/marcus.milne/Documents/iOS7/simplegcdserver/simplegcdserver/main.m:16
The problem seems to be with accessing MPAVItem.
The files "video.html" and "Fishmonger-Salmon_01_2.mp4" are being served locally. You can get a copy of the original mp4 from here http://kikkit-demo.s3.amazonaws.com/dev/Preview/370/Fishmonger-Salmon_01_2.mp4
Is there any way I can bind to 127.0.0.1 only?
Loving GCDWebserver so far!
I tried to serve an audio data file from user ipod library:
return [GCDWebServerDataResponse responseWithData:data contentType:@"audio/mp4"];
where data is the NSData * from a MPMediaItem.
I have this log when the url handler is called
[DEBUG] Did open connection on socket 34
[DEBUG] Connection received 320 bytes on socket 34
[DEBUG] Connection on socket 34 processing GET request for "/audioData" (0 bytes body)
[DEBUG] Connection sent 172 bytes on socket 34
// idem several times
[DEBUG] Connection sent 32768 bytes on socket 34
[DEBUG] Connection sent 5372 bytes on socket 34
[DEBUG] Did close connection on socket 34
[DEBUG] Did open connection on socket 34
[DEBUG] Connection received 321 bytes on socket 34
[DEBUG] Connection on socket 34 processing GET request for "/audioData" (0 bytes body)
[DEBUG] Connection sent 172 bytes on socket 34
[DEBUG] Connection sent 32768 bytes on socket 34
[DEBUG] Connection sent 32768 bytes on socket 34
[DEBUG] Connection sent 32768 bytes on socket 34
[DEBUG] Connection sent 32768 bytes on socket 34
[ERROR] Error while writing to socket 34: Broken
At the second call I have the same response and
[DEBUG] Did close connection on socket 34
To me it seems that the response body is 0 bytes
[DEBUG] Connection on socket 34 processing GET request for "/audioData" (0 bytes body)
but my NSData is actually filled in.
Where I'm wrong?
I want to preface by saying it is entirely possible that the fault is somewhere in my code but I can't find an obvious place that would be leaking on my side. I can consistently reproduce this doing the following:
Here's a link to the trace:
https://www.dropbox.com/sh/vv27heosugeym5y/_10rs09hI3
And here are some screenshots of the run:
The stack suggests that on my side the problem is in this method and even wrapping an autoreleasepool and manually nilling out the GCDWebServerDataRequest isn't doing it.
+ (GCDWebServerResponse *)createWithRequest:(GCDWebServerRequest *)request
withResource:(TGRESTResource *)resource
usingDatastore:(TGRESTStore *)store
{
NSParameterAssert(request);
NSParameterAssert(resource);
NSParameterAssert(store);
@autoreleasepool {
GCDWebServerDataRequest *dataRequest = (GCDWebServerDataRequest *)request;
NSDictionary *body;
if ([request.contentType hasPrefix:@"application/json"]) {
NSError *jsonError;
body = [NSJSONSerialization JSONObjectWithData:dataRequest.data options:NSJSONReadingAllowFragments error:&jsonError];
if (jsonError) {
return [GCDWebServerResponse responseWithStatusCode:400];
}
} else if ([request.contentType hasPrefix:@"application/x-www-form-urlencoded"]) {
NSString* charset = TGExtractHeaderValueParameter(request.contentType, @"charset");
NSString* formURLString = [[NSString alloc] initWithData:dataRequest.data encoding:TGStringEncodingFromCharset(charset)];
body = TGParseURLEncodedForm(formURLString);
}
Class <TGRESTSerializer> serializer;
if (store.server.serializers[resource.name]) {
serializer = store.server.serializers[resource.name];
} else {
serializer = store.server.defaultSerializer;
}
body = [serializer requestParametersWithBody:body resource:resource];
NSError *error;
NSDictionary *sanitizedBody = [self sanitizedPropertiesForResource:resource withProperties:body];
if (sanitizedBody.allKeys.count == 0) {
return [GCDWebServerResponse responseWithStatusCode:400];
}
NSDictionary *newObject = [store createNewObjectForResource:resource withProperties:sanitizedBody error:&error];
body = nil;
dataRequest = nil;
sanitizedBody = nil;
if (error) {
return [self errorResponseBuilderWithError:error];
}
return [GCDWebServerDataResponse responseWithJSONObject:[serializer dataWithSingularObject:newObject resource:resource]];
}
}
Title is all.
I tried GCDWebServer in OSX and iOS.
In iOS, the server process does not suspend a main thread.
But, in OSX it does.
I don't think up goot workaround, thank you.
See https://github.com/swisspol/ComicFlow/issues/31 for details
I've planned to develop in-app API proxy server with GCDWebServer and AFNetworking. Because of not every maintainer provide clean API for their service=(
As you know, AFNetworking use GCD callback system. GCDWebServer works in sync mode and I must sync AFNetworking callbacks in handler.
May be, you'll redesign handler system as it done in Express.js by passing callback as parameter in processBlock instead of return value? Something like this:
typedef void (^GCDWebServerResponseBlock)(GCDWebServerResponse* response);
typedef void (^GCDWebServerProcessBlock)(GCDWebServerRequest* request, GCDWebServerResponseBlock responseCallback);
There are several problems with contentLength
.
For one I think it should be of type unsigned long long
(also the return type of the fileSize
property in NSFileAttributes
). Currently we're running into problems with files larger than 4 GB (which is not an unlikely scenario, i.e. using the webserver to stream HQ movies for AirPlay on local WiFi).
Furthermore using NSNotFound
as a special value for contentLength
is problematic.
The NSNotFound
is NSIntegerMax
which is NSUIntegerMax/2
and therefore totally within the range of contentLength
.
I'd be glad to send a pull request for the first problem, but the second problem is more of a conceptual nature. Fixing problem no 1 doesn't make no 2 worse, so I'd suggest doing it anyway ;)
Any thoughts?
PS: still got much love for GCDWebServer! Thanks ๐
When installed via CocoaPods in a new iOS project, building for the simulator fails with the following errors:
Undefined symbols for architecture i386:
"_UTTypeCopyPreferredTagWithClass", referenced from:
_GCDWebServerGetMimeTypeForExtension in libPods.a(GCDWebServerFunctions.o)
"_UTTypeCreatePreferredIdentifierForTag", referenced from:
_GCDWebServerGetMimeTypeForExtension in libPods.a(GCDWebServerFunctions.o)
"_kUTTagClassFilenameExtension", referenced from:
_GCDWebServerGetMimeTypeForExtension in libPods.a(GCDWebServerFunctions.o)
"_kUTTagClassMIMEType", referenced from:
_GCDWebServerGetMimeTypeForExtension in libPods.a(GCDWebServerFunctions.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
These are defined in <MobileCoreServices/UTType.h>
, which is imported in GCDWebServerFunctions.m
. When building from source, this works fine, but seems to fail as a pod, I assume because the framework isn't explicitly linked in the podspec.
Changing the Core
subspec to the following seemed to fix it for me:
s.subspec 'Core' do |cs|
cs.source_files = 'GCDWebServer/**/*.{h,m}'
cs.requires_arc = true
cs.ios.framework = 'MobileCoreServices'
cs.ios.library = 'z'
cs.osx.framework = 'SystemConfiguration'
cs.osx.library = 'z'
cs.compiler_flags = '-DNDEBUG'
end
I was going to create a pull request, but it's a very small change and I wanted to see if there was a reason you weren't linking them by default.
See #45 for details
GCDWebServer is simple and powerful.
I want to implement a WebDAV server with it. And need support Chunked transfer encoding while handle PUT command.
Hi, I use responseWithData for send server 3.3 MB mp4 file. But not working . Then I tried to send NSData as Partial Content. Then I look your method - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment
Then this method inside used "Content-Range". I wrote new method use it same code in GCDWebServerDataResponse
class. But I have a problem. My mp4 files length 34 second.
15 seconds, which works very well, but then gets stuck. Please help me. using a "Content-Range" need to find a way to send server.
I have written my code :
- (instancetype)initWithDataPartialContent:(NSData*)data contentType:(NSString*)contentType byteRange:(NSRange)range{
if (data == nil) {
DNOT_REACHED();
ARC_RELEASE(self);
return nil;
}
struct stat info;
if (GCDWebServerIsValidByteRange(range)) {
if (range.location != NSNotFound) {
range.location = MIN(range.location, (NSUInteger)info.st_size);
range.length = MIN(range.length, (NSUInteger)info.st_size - range.location);
} else {
range.length = MIN(range.length, (NSUInteger)info.st_size);
range.location = (NSUInteger)info.st_size - range.length;
}
if (range.length == 0) {
ARC_RELEASE(self);
return nil; // TODO: Return 416 status code and "Content-Range: bytes */{file length}" header
}
}
if ((self = [super init])) {
_data = ARC_RETAIN(data);
if (range.location != NSNotFound) {
[self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent];
[self setValue:[NSString stringWithFormat:@"bytes %i-%i/%i", (int)range.location, (int)(range.location + range.length - 1), (int)info.st_size] forAdditionalHeader:@"Content-Range"];
//LOG_DEBUG(@"Using content bytes range [%i-%i] for file \"%@\"", (int)range.location, (int)(range.location + range.length - 1), path);
}
NSLog(@"RANGE Length %lu",(unsigned long)range.length);
self.contentType = contentType;
self.contentLength = (range.location != NSNotFound ? range.length : (NSUInteger)info.st_size);
self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec);
self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec];
//self.contentLength = data.length;
}
return self;
}
static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)];
}
Seems like you could also use GCD for manage socket communication.
http://www.mikeash.com/pyblog/friday-qa-2009-12-11-a-gcd-case-study-building-an-http-server.html
This library looks great. Are you considering adding web socket support in the future?
Enabling warnings -Wshadow
reveals some minor issues.
Example: The following lines are not easily understandable due to the re-use of the variable name buffer
:
- (void)_readDataWithCompletionBlock:(ReadDataCompletionBlock)block {
[self _readBufferWithLength:SIZE_T_MAX completionBlock:^(dispatch_data_t buffer) {
if (buffer) {
NSMutableData* data = [[NSMutableData alloc] initWithCapacity:dispatch_data_get_size(buffer)];
dispatch_data_apply(buffer, ^bool(dispatch_data_t region, size_t offset, const void* buffer, size_t size) {
[data appendBytes:buffer length:size];
return true;
});
block(data);
ARC_RELEASE(data);
} else {
block(nil);
}
}];
}
See #26 for an example use
I need decode file before send to response.
I create subclass WebServerDecryptedFileResponse
of GCDWebServerFileResponse
and overwrite method readData
:
- (NSData *)readData:(NSError *__autoreleasing *)error
{
NSData *readData = [super readData:error];
if (readData.length != 0) {
readData = [readData decodedData];
}
return readData;
}
Server starts with code:
[_server addHandlerWithMatchBlock:^GCDWebServerRequest *(NSString* requestMethod, NSURL* requestURL, NSDictionary* requestHeaders, NSString* urlPath, NSDictionary* urlQuery) {
if (![requestMethod isEqualToString:@"GET"]) {
return nil;
}
return [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
} processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
GCDWebServerResponse* response = nil;
NSString *filePath = [_path stringByAppendingPathComponent:request.path];
BOOL isDirectory;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory] && !isDirectory) {
response = [WebServerDecryptedFileResponse responseWithFile:filePath];
}
if (!response) {
response = [GCDWebServerResponse responseWithStatusCode:kGCDWebServerHTTPStatusCode_NotFound];
}
return response;
}];
The problem is UIWebView
did not load with error:
Code=-1005 "The network connection was lost."
.
Method readData
calls twice and the first time it seems all is well, but when readData
with length 0
UIWebView
show error.
What's wrong?
Thanks!
This header can be either set to the "ETag" or "Last-Modified" value for the entity. If they don't match the current values, the "Range" header should be ignored and the entire resource returned with a 200 status, otherwise only the required byte range should be returned with a 206 status.
Currently GCDWebServer implements the latter but not the former.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.27
https://github.com/onevcat/VVDocumenter-Xcode
And verify this works with http://cocoadocs.org/docsets/GCDWebServer/
It would be nice to have this project running on other platforms beside OS X. It could be accomplished by using GNUstep.
I've tried to make things work, but with poor success.
Main problem is the CFNetwork (mainly calls to CFNetServices ) and CoreServices dependancy.
I think that could be possible to port CFNetServices function calls to NSNetServices ( since it is implemented in GNUstep) and see what we could do for CoreServices call.
I'll give it a try when I can.
I opened an issue to let you know about that and ask you if there's something I've to know before starting working on it (maybe some hard reason why dependency on those framework cannot be removed)
And of course recruiting someone who would help me do it :D
Bests
I'm using GCDWebServer on OS X, and I'm finding that it's ignoring INT and TERM signals after a while running.
I'm using an NSApplication - a normal Cocoa app, but without any visible UI, to do some offscreen rendering and returning images over HTTP. I run the application binary directly from the command line Name.app/Contents/MacOS/Name
.
After a period of running - sometimes as little as an hour, hitting Ctrl-C no longer stops the application, and the signal seems to be ignored. Performing a 'Quit' from Activity Monitor does the same. Only a 'Force Quit' terminates the application.
Even though I'm running from a command line application I'm using startWithOptions
, not runWithOptions
, because I don't want to lock the main thread, which is sometimes used by Cocoa internals for drawing.
Any idea what's going on?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.