GCDWebServer

GCDWebServer

摘要

關(guān)鍵詞:iOS服務(wù)器框架,基于GCD

GCDWebServer是一個現(xiàn)代和輕量級的基于 HTTP 1.1的服務(wù)器所禀,它的設(shè)計旨在嵌入OS X和iOS應(yīng)用程序中蛹屿。它的實現(xiàn)在一開始就考慮了以下目標(biāo):

  • 一個優(yōu)雅輕巧的使用架構(gòu)帶有四個核心的類:請求類屁奏,連接類,請求類和響應(yīng)類(詳情請參閱“了解GCDWebServer的架構(gòu)”下)错负。
  • 一個精心設(shè)計的可以輕松集成和定制完整的方便查看的頭文件
  • 完全使用基于事件驅(qū)動的Grand Central Dispatch以求最佳性能和并發(fā)能力
  • 不依賴任何第三方的源碼
  • 新的友好的BSD許可證下可使用

其他的內(nèi)置功能

  • 實現(xiàn)-對于進(jìn)入的HTTP請求采用完全異步的處理手段
  • 最小化內(nèi)存消耗-盡可能把大量的HTTP請求和響應(yīng)體放在磁盤流中
  • 使用 "application/x-www-form-urlencoded" 或者 "multipart/form-data" 編碼 解析網(wǎng)站表單提交
  • 對HTTP體的請求和響應(yīng)采用JSON解析和序列化
  • 對HTTP體的請求和響應(yīng) 分塊傳輸解碼
  • 對HTTP體的請求和響應(yīng) 使用gzip對HTTP進(jìn)行壓縮
  • 對請求的本地文件的范圍也支持
  • 密碼保護(hù)有基本的摘要接入認(rèn)證-維基百科
  • 自動處理iOS apps前臺坟瓢,后臺和假死狀態(tài)的轉(zhuǎn)換過渡
  • 全面支持IPv4和IPv6
  • NAT端口映射(僅限IPv4)
擴(kuò)展
  • GCDWebUploader : GCDWebServer的子類,使用Web瀏覽器實現(xiàn) 上傳和下載文件的接口
  • GCDWebDAVServer : GCDWebServer的子類犹撒,實現(xiàn)1級WebDAV服務(wù)器(與OS X的Finder部分2級支持)
暫不支持(非一個嵌入式HTTP服務(wù)器必須的)
  • 長連接
  • HTTPS

使用條件

  • OS X 10.7以后(X86_64)
  • iOS 5.0之后(armv7,armv7s或者arm64)
  • ARC的內(nèi)存管理(MRC使用GCDWebServer 3.1和更早版本)

開始使用

下載或查看GCDWebServer的最新版本折联,直接添加整個“ GCDWebServer ”子文件夾到Xcode項目。如果您打算使用像GCDWebDAVServer或GCDWebUploader擴(kuò)展之一识颊,還要添加這些子文件夾诚镰。

  • 1.如果是直接手動添加GCDWebServer,那么第一步需要添加動態(tài)庫libz(路徑: Target > Build Phases > Link Binary With Libraries) 第二步添加 $(SDKROOT)/usr/include/libxml2)到header search paths(路徑:arget > Build Settings > HEADER_SEARCH_PATHS)祥款;

  • 2.安裝使用CocoaPods可以簡單的添加(通過添加下面到Podfile中即可):

    pod "GCDWebServer", "~> 3.0"

  • 如果你還想使用GCDWebUploader 清笨,使用該行:

    pod "GCDWebServer/WebUploader", "~> 3.0"

  • GCDWebDAVServer使用下面:

    pod "GCDWebServer/WebDAV", "~> 3.0"

最后終端輸入命令:$ pod install

您還可以使用由Carthage加入這一行到你的Cartfile ( 3.2.5第一次正式發(fā)布與Carthage支持) :

github "swisspol/GCDWebServer" ~> 3.2.5

然后終端輸入命令 $ carthage update 添加生成的frameworks到你的xcode項目中即可(詳情查看Carthage instructions

幫助與支持

有關(guān)使用GCDWebServer的幫助下,最好把你的問題上在StackOverflow貼上GCDWebserver標(biāo)簽刃跛。

請務(wù)必先雖然閱讀整本自述抠艾!

Hello World

下面代碼介紹了如何實現(xiàn)在8080端口上運(yùn)行,而且無論任何請求服務(wù)器都會返回一個“ Hello World”的HTML頁面桨昙。

由于GCDWebServer使用GCD塊來處理請求检号,沒有使用子類或者代理,因此代碼整體看起來很干凈蛙酪。

重要提示:如果不使用的CocoaPods 齐苛,務(wù)必在項目中將libz進(jìn)行系統(tǒng)共享庫添加到Xcode的target中。

OS X版本(命令行工具) :

 #import "GCDWebServer.h"
 #import "GCDWebServerDataResponse.h"

int main(int argc, const char* argv[]) {
  @autoreleasepool {

    // Create server
    GCDWebServer* webServer = [[GCDWebServer alloc] init];

    // Add a handler to respond to GET requests on any URL
    [webServer addDefaultHandlerForMethod:@"GET"
                             requestClass:[GCDWebServerRequest class]
                             processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {

      return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];

    }];

    // Use convenience method that runs server on port 8080
    // until SIGINT (Ctrl-C in Terminal) or SIGTERM is received
    [webServer runWithPort:8080 bonjourName:nil];
    NSLog(@"Visit %@ in your web browser", webServer.serverURL);

  }
  return 0;
}

iOS版本:

 #import "GCDWebServer.h"
 #import "GCDWebServerDataResponse.h"

@interface AppDelegate : NSObject <UIApplicationDelegate> {
  GCDWebServer* _webServer;
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {

  // Create server
  _webServer = [[GCDWebServer alloc] init];

  // Add a handler to respond to GET requests on any URL
  [_webServer addDefaultHandlerForMethod:@"GET"
                            requestClass:[GCDWebServerRequest class]
                            processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {

    return [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];

  }];

  // Start server on port 8080
  [_webServer startWithPort:8080 bonjourName:nil];
  NSLog(@"Visit %@ in your web browser", _webServer.serverURL);

  return YES;
}

@end

OS X Swift(命令行工具) :

webServer.swift
import Foundation
import GCDWebServers

func initWebServer() {

    let webServer = GCDWebServer()

    webServer.addDefaultHandlerForMethod("GET", requestClass: GCDWebServerRequest.self, processBlock: {request in
    return GCDWebServerDataResponse(HTML:"<html><body><p>Hello World</p></body></html>")

    })

    webServer.runWithPort(8080, bonjourName: "GCD Web Server")

    print("Visit \(webServer.serverURL) in your web browser")
}
WebServer-Bridging-Header.h
 #import <GCDWebServers/GCDWebServer.h>
 #import <GCDWebServers/GCDWebServerDataResponse.h>

iOS Apps中基于Web 的上傳

GCDWebUploader是GCDWebServer的子類滤否,提供了一個現(xiàn)成供 HTML5文件上傳下載脸狸。GCDWebUploader讓用戶可以在瀏覽器里使用一個干凈的UI來上傳,下載,刪除文件炊甲,以及在iOS應(yīng)用的沙盒中的目錄創(chuàng)建目錄泥彤。

從你的瀏覽器中簡單地實例化GCDWebUploader和運(yùn)行然后訪問 http://{YOUR-IOS-DEVICE-IP-ADDRESS}/

 #import "GCDWebUploader.h"

@interface AppDelegate : NSObject <UIApplicationDelegate> {
  GCDWebUploader* _webUploader;
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
  NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  _webUploader = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
  [_webUploader start];
  NSLog(@"Visit %@ in your web browser", _webUploader.serverURL);
  return YES;
}

@end
在iOS應(yīng)用WebDAV服務(wù)器

GCDWebDAVServer 是GCDWebServer的子類提供了一個兼容的WebDAV服務(wù)器。 使用任何的WebDAV服務(wù)器像Transmit(Mac),ForkLift (Mac) 或者 CyberDuck(Mac / Windows)一樣可以在ISO沙盒目錄中讓用戶上傳卿啡,下載吟吝,刪除或者創(chuàng)建目錄文件。

簡單地實例化和運(yùn)行GCDWebDAVServer颈娜,然后使用WebDAV連接到 http://{自己的IOS設(shè)備的IP地址}/ :

 #import "GCDWebDAVServer.h"

@interface AppDelegate : NSObject <UIApplicationDelegate> {
  GCDWebDAVServer* _davServer;
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
  NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  _davServer = [[GCDWebDAVServer alloc] initWithUploadDirectory:documentsPath];
  [_davServer start];
  NSLog(@"Visit %@ in your WebDAV client", _davServer.serverURL);
  return YES;
}

@end

Serving a Static Website 服務(wù)于靜態(tài)網(wǎng)站

GCDWebServer有一個固定的handler用來遞歸式的服務(wù)一個目錄(一個容許你控制并設(shè)置HTTP header的 "Cache-control"剑逃,Cache-control用于控制HTTP緩存)

OS X 版(command line tool):

import "GCDWebServer.h"

int main(int argc, const char* argv[]) {
@autoreleasepool {

GCDWebServer* webServer = [[GCDWebServer alloc] init];
[webServer addGETHandlerForBasePath:@"/" directoryPath:NSHomeDirectory() indexFilename:nil cacheAge:3600 allowRangeRequests:YES];
[webServer runWithPort:8080];
  }
   return 0;
 }

使用 GCDWebServer

你可以通過創(chuàng)建一個實例 GCDWebServer類開始。注意:你可以在同一個應(yīng)用程序上運(yùn)行多個web服務(wù)器只要這些web服務(wù)器是掛在不同的端口官辽。
然后你可以添加一個或者多個“處理”給服務(wù)器:每一個處理器都有機(jī)會去處理傳入的Web請求并且提供響應(yīng)蛹磺。處理程序我們叫做LIFO隊列,所以最新加入的“處理器”會覆寫之前所有添加的“處理程序”同仆。

理解 GCDWebServer的架構(gòu)

GCDWebServer的體系結(jié)構(gòu)包括只有4個核心類:
GCDWebServer 負(fù)責(zé)管理監(jiān)聽新的HTTP連接和服務(wù)器使用的一系列的處理程序列表 的接口socket.

GCDWebServerConnection 是由GCDWebServer來實例化處理每一個新的HTTP連接萤捆。每一個GCDWebServerConnection實例一直保持活躍狀態(tài)一直到連接被關(guān)閉! 你可不能直接使用這個類俗批,但是由于它是暴露的所以你可以繼承至它來覆寫一些hooks.

GCDWebServerRequest 由GCDWebServerConnection在接收到HTTP 表頭后實例化 創(chuàng)建俗或。 用它來包裝請求和處理HTTP主體(如果有主體的話)。GCDWebServer 包含了幾個GCDWebServerRequest的子類來處理常見情況下的情況:如存儲 body 到內(nèi)存或者傳輸?shù)酱疟P的一個文件中岁忘。

GCDWebServerResponse 由請求處理器創(chuàng)建 和 包裝該響應(yīng)HTTP headers和一些可選擇的body. GCDWebServer 也是通過由幾個GCDWebServerResponse的子類來處理常見的情況的如內(nèi)存中的HTML文本或者從磁盤來傳輸一個文件時辛慰,

GCDWebServer 實現(xiàn)

GCDWebServer的實現(xiàn)依賴于“處理程序” 來處理傳入的Web請求并且做出響應(yīng)。 “處理程序”通過GCD塊來實現(xiàn)的使得GCDWebServer方便你使用干像。然而帅腌,由于在GCD中“處理程序”是在任意的線程中執(zhí)行,所以要注意的是線程安全和同一程序重復(fù)執(zhí)行問題麻汰。

處理程序用到2個GCD塊:
GCDWebServerMatchBlock 會被 在添加到GCDWebServer中的每一個"處理程序"所調(diào)用只要一個web請求已經(jīng)開始后(如HTTP 表頭已經(jīng)收到)狞膘。它可以傳遞Web請求的基本信息(HTTP method, URL, headers...)而且必須要決定是否會處理這個請求。 如果返回yes什乙,那么必須要返回一個新的這有這些信息的GCDWebServerRequest實例(看上面的GCDWebServerRequest),否則它只是返回nil.

之后已球,Web請求已經(jīng)被完全接收并傳遞在上一步創(chuàng)建的GCDWebServerRequest實例GCDWebServerProcessBlock或GCDWebServerAsyncProcessBlock被調(diào)用臣镣。它必須返回同步(如果使用GCDWebServerProcessBlock)或異步(如果使用GCDWebServerAsyncProcessBlock)一個GCDWebServerResponse實例(見上文)或nil ,nil返回一個500的HTTP狀態(tài)代碼返回給客戶端智亮。一般我們推薦針對錯誤 返回一個GCDWebServerErrorResponse實例 以便可以把更多有用信息返回給客戶端忆某。

請注意:GCDWebServer的大多數(shù)方法來添加handlers只需要GCDWebServerProcessBlock或GCDWebServerAsyncProcessBlock ,因為它們已經(jīng)提供了一種內(nèi)置位于GCDWebServerMatchBlock中--例如 通過正則Regex匹配URL路徑。

異步響應(yīng)HTTP

GCDWebServer 3.0新增特性是異步地處理HTTP請求阔蛉,如增加了 請求服務(wù)器后可以異步生成GCDWebServerResponse 的handlers弃舒,
這一過程通過使用GCDWebServerAsyncProcessBlock代替GCDWebServerProcessBlock的處理程序來實現(xiàn)。下面是一個例子:

(同步版)handler在響應(yīng)HTTP后會產(chǎn)生blocks回調(diào):
    [webServer addDefaultHandlerForMethod:@"GET"
                             requestClass:[GCDWebServerRequest class]
                             processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
    
      GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];
      return response;
    
    }];
(異步版本) handler會立即返回結(jié)果并會在響應(yīng)HTTP后回調(diào)GCDWebServer
[webServer addDefaultHandlerForMethod:@"GET"
                         requestClass:[GCDWebServerRequest class]
                    asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {

  // Do some async operation like network access or file I/O (simulated here using dispatch_after())
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    GCDWebServerDataResponse* response = [GCDWebServerDataResponse responseWithHTML:@"<html><body><p>Hello World</p></body></html>"];
    completionBlock(response);
  });

}];
(高級異步版本)handler會立即返回一個HTTP本身異步內(nèi)容流的HTTP響應(yīng):
[webServer addDefaultHandlerForMethod:@"GET"
                         requestClass:[GCDWebServerRequest class]
                         processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {

  NSMutableArray* contents = [NSMutableArray arrayWithObjects:@"<html><body><p>\n", @"Hello World!\n", @"</p></body></html>\n", nil];  // Fake data source we are reading from
  GCDWebServerStreamedResponse* response = [GCDWebServerStreamedResponse responseWithContentType:@"text/html" asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock completionBlock) {

    // Simulate a delay reading from the fake data source
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      NSString* string = contents.firstObject;
      if (string) {
        [contents removeObjectAtIndex:0];
        completionBlock([string dataUsingEncoding:NSUTF8StringEncoding], nil);  // Generate the 2nd part of the stream data
      } else {
        completionBlock([NSData data], nil);  // Must pass an empty NSData to signal the end of the stream
      }
    });

  }];
  return response;

}];
注意:甚至你可以結(jié)合異步的和高級異步這兩個版本去異步返回一個異步的HTTP響應(yīng)!

GCDWebServer & iOS APPs的后臺運(yùn)行模式

當(dāng)iOS APP在進(jìn)行網(wǎng)絡(luò)請求時聋呢,我們必須注意當(dāng)我們把應(yīng)用程序壓入后臺后會發(fā)生什么情況苗踪。 一般情況下,應(yīng)用程序進(jìn)入后臺我們應(yīng)該停止網(wǎng)絡(luò)請求當(dāng)應(yīng)用程序再次進(jìn)入前臺時我們再重新開始網(wǎng)絡(luò)請求削锰。
這使得情況可能會較為復(fù)雜通铲,考慮到當(dāng)服務(wù)器需要停止服務(wù)時他們?nèi)匀辉诒3种粩噙B接的狀態(tài)。
幸運(yùn)的事是GCDWebServer會代替我們自動完成以上的工作:

  • GCDWebServer 會開啟后臺模式器贩,當(dāng)?shù)谝淮蜨TTP連接開始至最后一個HTTP請求結(jié)束颅夺,這樣就阻止了應(yīng)用系統(tǒng)一旦進(jìn)入后臺就會被iOS系統(tǒng)殺死,而且也會把HTTP連接一起殺死蛹稍。

  • 當(dāng)我們的應(yīng)用程序在后臺時吧黄,只要新的HTTP連接一直保持創(chuàng)建,后臺任務(wù)就會持續(xù)進(jìn)行唆姐,iOS系統(tǒng)就不會kill我們的應(yīng)用程序(除了app很快的意外的內(nèi)存升高問題).

  • 如果應(yīng)用程序一直保持后臺運(yùn)行當(dāng)一個HTTP請求都沒有打開拗慨,GCDWebServer會立即結(jié)束自己 而且 一旦調(diào)用了 -stop方法就會停止接收新的HTTP請求(這一模式在 GCDWebServerOption_AutomaticallySuspendInBackground 選項中無效).
    +如果app進(jìn)入了前臺模式而且GCDWebServer是在暫停期間, 一旦調(diào)用了 -start 方法厦酬,GCDWebServer會自動的結(jié)束自己暫停狀態(tài)開始接收新的HTTP連接胆描。

  • HTTP連接經(jīng)常是分批次(或者突然性)發(fā)起的,例如當(dāng)加載一個帶有多個資源文件的網(wǎng)頁時就會這樣仗阅。 當(dāng)很靠后的HTTP 連接已經(jīng)被關(guān)閉時就很難去精確地檢測到了:它可能同一批的2個連續(xù)的HTTP連接部分很短的時間的延遲昌讲,而不是覆蓋。如果GCDWebServer在它們之間的時間縫隙里停止在客戶端了就不太好了(估計這樣的話效率就低了)减噪,GCDWebServerOption_ConnectedStateCoalescingInterval這個enum值通過優(yōu)雅的強(qiáng)制GCDWebServer 在每一個HTTP連接結(jié)束后等待一定時間的間隔短绸,以防一個新的HTTP請求會在這個很短的時間間隔里被再次創(chuàng)建。

GCDWebServer日志

無論出于調(diào)試還是情報的目的筹裕, GCDWebServer無論何時都會記錄messages醋闭。此外,在“調(diào)試”模式與“釋發(fā)布”模式建設(shè)GCDWebServer時朝卒,它會記錄更多的信息,但也進(jìn)行了一些內(nèi)部的重復(fù)性內(nèi)容檢查抗斤。要啟用此行為,編譯時GCDWebServer定義預(yù)處理器時設(shè)置常量DEBUG = 1 龙宏。在Xcode目標(biāo)設(shè)置,這可以通過增加DEBUG = 1 開啟 “調(diào)試”模式和 設(shè)置GCC_PREPROCESSOR_DEFINITIONS完成伤疙。最后银酗,您還可以通過運(yùn)行時調(diào)用類方法 +[GCDWebServer setLogLevel:]來完成。

  • 默認(rèn)情況下黍特, GCDWebServer記錄的所有消息都發(fā)送到其內(nèi)置的日志記錄功能,它只是輸出到stderr (假設(shè)終端設(shè)備連接了) 衅澈。為了更好地依靠日志的記錄來完善APP键菱,你可能想使用另一種記錄工具。

  • GCDWebServer 對XLFacility自動支持(GCDWebServer的同一個作者而且開源)和CocoaLumberjack 今布。如果其中一方是在同一個Xcode項目部默, GCDWebServer會自動用它代替內(nèi)置的日志記錄功能(見GCDWebServerPrivate.h的實施細(xì)節(jié))侵蒙。

它也可以使用自定義日志記錄功能 - 見GCDWebServer.h獲取更多信息傅蹂。

高級示例1 :實現(xiàn)HTTP重定向

下面是重定向的例子處理程序“/ ”到“/index.htm“,使用的GCDWebServerResponse的簡便方法(它會自動設(shè)置HTTP狀態(tài)代碼和”位置“標(biāo)頭) :

[self addHandlerForMethod:@"GET"
                     path:@"/"
             requestClass:[GCDWebServerRequest class]
             processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {

  return [GCDWebServerResponse responseWithRedirect:[NSURL URLWithString:@"index.html" relativeToURL:request.URL]
                                          permanent:NO];

}];
高級示例2 :實現(xiàn)形式

要實現(xiàn)HTTP表單份蝴,你需要兩個處理程序:

  • 一個獲取處理程序不期望在HTTP請求任何機(jī)構(gòu),因此使用GCDWebServerRequest類浸卦。處理程序生成包含一個簡單的HTML表單的響應(yīng)案糙。

  • 另一個POST處理器期望表單值是在HTTP請求和百分比編碼的主體。幸運(yùn)的是时捌, GCDWebServer提供請求類GCDWebServerURLEncodedFormRequest能夠自動解析這樣的主題。處理程序簡單地顯示對應(yīng)的用戶提交的表單中的值稚叹。

      [webServer addHandlerForMethod:@"GET"
                                path:@"/"
                        requestClass:[GCDWebServerRequest class]
                        processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
      
        NSString* html = @" \
          <html><body> \
            <form name=\"input\" action=\"/\" method=\"post\" enctype=\"application/x-www-form-urlencoded\"> \
            Value: <input type=\"text\" name=\"value\"> \
            <input type=\"submit\" value=\"Submit\"> \
            </form> \
          </body></html> \
        ";
        return [GCDWebServerDataResponse responseWithHTML:html];
      
      }];
      
      [webServer addHandlerForMethod:@"POST"
                                path:@"/"
                        requestClass:[GCDWebServerURLEncodedFormRequest class]
                        processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
      
        NSString* value = [[(GCDWebServerURLEncodedFormRequest*)request arguments] objectForKey:@"value"];
        NSString* html = [NSString stringWithFormat:@"<html><body><p>%@</p></body></html>", value];
        return [GCDWebServerDataResponse responseWithHTML:html];
          }];
    
高級示例3 :服務(wù)動態(tài)網(wǎng)站

GCDWebServer提供的擴(kuò)展類 - GCDWebServerDataResponse拿诸,可以返回從模板和一組變量中(使用格式%變量%)生成的HTML內(nèi)容。這是一個非常基本的模板系統(tǒng)凡桥,并且打算以它為出發(fā)點通過繼承GCDWebServerResponse建造更先進(jìn)的系統(tǒng)。

假設(shè)你的應(yīng)用程序有一個網(wǎng)站目錄在包含了HTML模板文件和相應(yīng)的CSS啊掏,腳本和圖像。這是很容易把它變成一個動態(tài)的網(wǎng)站:

// Get the path to the website directory
NSString* websitePath = [[NSBundle mainBundle] pathForResource:@"Website" ofType:nil];

// Add a default handler to serve static files (i.e. anything other than HTML files)
[self addGETHandlerForBasePath:@"/" directoryPath:websitePath indexFilename:nil cacheAge:3600 allowRangeRequests:YES];

// Add an override handler for all requests to "*.html" URLs to do the special HTML templatization
[self addHandlerForMethod:@"GET"
                pathRegex:@"/.*\.html"
             requestClass:[GCDWebServerRequest class]
             processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {

    NSDictionary* variables = [NSDictionary dictionaryWithObjectsAndKeys:@"value", @"variable", nil];
    return [GCDWebServerDataResponse responseWithHTMLTemplate:[websitePath stringByAppendingPathComponent:request.path]
                                                    variables:variables];

}];

// Add an override handler to redirect "/" URL to "/index.html"
[self addHandlerForMethod:@"GET"
                     path:@"/"
             requestClass:[GCDWebServerRequest class]
             processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {

    return [GCDWebServerResponse responseWithRedirect:[NSURL URLWithString:@"index.html" relativeToURL:request.URL]
                                            permanent:NO];

];
最后一個例子:iOS 文件的下載和上傳

GCDWebServer最初被寫為iPad上的ComicFlow漫畫閱讀器應(yīng)用程序刹孔。它允許用戶使用其Web瀏覽器通過WiFi連接到他們的iPad 娜睛,然后上傳,下載和整理漫畫文件的應(yīng)用程序內(nèi)畦戒。

ComicFlow是完全開源的,你可以看到它是如何在WebServer.h和WebServer.m文件使用GCDWebServer 纵潦。

補(bǔ)充:github傳送門垃环,喜歡請Star

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市寥院,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌只磷,老刑警劉巖泌绣,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異元媚,居然都是意外死亡苗沧,警方通過查閱死者的電腦和手機(jī)刊棕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門甥角,熙熙樓的掌柜王于貴愁眉苦臉地迎上來识樱,“玉大人震束,你說我怎么就攤上這事当犯」复澹” “怎么了嘉栓?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵拓诸,是天一觀的道長。 經(jīng)常有香客問我恰响,道長,這世上最難降的妖魔是什么胚宦? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任枢劝,我火速辦了婚禮,結(jié)果婚禮上您旁,老公的妹妹穿的比我還像新娘。我一直安慰自己蚕脏,他們只是感情好侦锯,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著挣棕,像睡著了一般亲桥。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上词身,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天番枚,我揣著相機(jī)與錄音璧瞬,去河邊找鬼渐夸。 笑死渔欢,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的苫幢。 我是一名探鬼主播垫挨,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哀峻!你這毒婦竟也來了哲泊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤育特,失蹤者是張志新(化名)和其女友劉穎先朦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喳魏,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡截酷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了三热。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片三幻。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖念搬,靈堂內(nèi)的尸體忽然破棺而出摆出,到底是詐尸還是另有隱情,我是刑警寧澤偎漫,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布有缆,位于F島的核電站,受9級特大地震影響杯矩,放射性物質(zhì)發(fā)生泄漏袖外。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一泌射、第九天 我趴在偏房一處隱蔽的房頂上張望蚣驼。 院中可真熱鬧,春花似錦颖杏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至量愧,卻和暖如春帅矗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背浑此。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留紊馏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓岸啡,卻偏偏與公主長得像赫编,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沛慢,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理团甲,服務(wù)發(fā)現(xiàn)黍聂,斷路器,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫匹厘、插件脐区、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,093評論 4 62
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,071評論 25 707
  • 十四班默伍,全班一人一本《談美》,都在讀炼蹦。好显设。 擔(dān)心讀不懂——今天的中國學(xué)生很少讀論理著作,遇上朱光潛捕捂,得到一點趣味斗搞,...
    行吟斯基閱讀 1,836評論 11 13
  • 我想當(dāng)一個傻子 活在自己的世界里 不去聽 塵世多嘈雜 不去看 人心多險惡 不去管 世事多糾纏 離別時 不會難過 再...
    藍(lán)綠小巨人閱讀 533評論 32 34