Overview
Comment: | Use dot syntax |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
58aa5e718e8fb629ed4f2e416cfbef9e |
User & Date: | js 2019-03-17 03:32:00 |
Context
2021-04-30
| ||
21:35 | Adjust to ObjFW changes Leaf check-in: 7b4329bd1c user: js tags: trunk | |
2019-03-17
| ||
03:32 | Use dot syntax check-in: 58aa5e718e user: js tags: trunk | |
2019-03-03
| ||
13:27 | Add support for TLS check-in: 441110b797 user: js tags: trunk | |
Changes
Changes to ConfigParser.m.
︙ | ︙ | |||
75 76 77 78 79 80 81 | [super dealloc]; } - (void)_parseConfig: (OFXMLElement *)config { void *pool = objc_autoreleasePoolPush(); | < | | | | | | | | | | | | | | | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | [super dealloc]; } - (void)_parseConfig: (OFXMLElement *)config { void *pool = objc_autoreleasePoolPush(); if (config.namespace != nil || ![config.name isEqual: @"ObjWebServer"]) [self _invalidConfig: @"Root element is not ObjWebServer"]; [self _parseListens: [config elementsForName: @"listen"]]; [self _parseModules: [config elementsForName: @"module"]]; objc_autoreleasePoolPop(pool); } - (void)_parseListens: (OFArray OF_GENERIC(OFXMLElement *) *)elements { OFMutableArray OF_GENERIC(ListenConfig *) *listenConfigs = [OFMutableArray array]; for (OFXMLElement *element in elements) { ListenConfig *listenConfig = [[[ListenConfig alloc] init] autorelease]; OFString *host = [element attributeForName: @"host"].stringValue; OFString *portString = [element attributeForName: @"port"].stringValue; OFXMLElement *TLS = [element elementForName: @"tls"]; if (host == nil) [self _invalidConfig: @"<listen/> is missing host attribute"]; if (portString == nil) [self _invalidConfig: @"<listen/> is missing port attribute"]; listenConfig.host = host; @try { intmax_t port = portString.decimalValue; if (port < 0 || port > 65535) @throw [OFInvalidFormatException exception]; listenConfig.port = port; } @catch (OFInvalidFormatException *e) { [self _invalidConfig: @"<listen/> has invalid port"]; } if (TLS != nil) { OFString *certificateFile = [TLS attributeForName: @"cert"].stringValue; OFString *keyFile = [TLS attributeForName: @"key"].stringValue; if (certificateFile == nil) [self _invalidConfig: @"<tls/> has no cert attribute"]; if (keyFile == nil) [self _invalidConfig: @"<tls/> has no key attribute"]; listenConfig.TLSCertificateFile = certificateFile; listenConfig.TLSKeyFile = keyFile; } [listenConfigs addObject: listenConfig]; } [listenConfigs makeImmutable]; _listenConfigs = [listenConfigs copy]; } - (void)_parseModules: (OFArray OF_GENERIC(OFXMLElement *) *)elements { OFMutableArray OF_GENERIC(OFXMLElement *) *modules = [OFMutableArray array]; for (OFXMLElement *element in elements) { OFString *path = [element attributeForName: @"path"].stringValue; OFString *prefix = [element attributeForName: @"prefix"].stringValue; if (path == nil || prefix == nil) [self _invalidConfig: @"<module/> has no path attribute"]; [modules addObject: element]; } |
︙ | ︙ |
Changes to ObjWebServer.m.
︙ | ︙ | |||
45 46 47 48 49 50 51 | _config = [[ConfigParser alloc] initWithConfigPath: @"ObjWebServer.xml"]; modules = [OFMutableArray array]; for (OFXMLElement *config in [_config modules]) { OFString *path = | | | | | | | | | | | | | | | | | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | _config = [[ConfigParser alloc] initWithConfigPath: @"ObjWebServer.xml"]; modules = [OFMutableArray array]; for (OFXMLElement *config in [_config modules]) { OFString *path = [config attributeForName: @"path"].stringValue; OFString *prefix = [config attributeForName: @"prefix"].stringValue; OFPlugin <Module> *module = [self loadModuleAtPath: path withConfig: config]; [modules addObject: [OFPair pairWithFirstObject: prefix secondObject: module]]; } [modules makeImmutable]; _modules = [modules copy]; for (ListenConfig *listenConfig in _config.listenConfigs) [self startWebserverWithListenConfig: listenConfig]; } - (OFPlugin <Module> *)loadModuleAtPath: (OFString *)path withConfig: (OFXMLElement *)config { OFPlugin <Module> *module; of_log(@"Loading module at %@", path); module = [OFPlugin pluginFromFile: path]; [module parseConfig: config]; return module; } - (void)startWebserverWithListenConfig: (ListenConfig *)listenConfig { OFHTTPServer *server = [OFHTTPServer server]; server.host = listenConfig.host; server.port = listenConfig.port; if (listenConfig.TLSCertificateFile != nil && listenConfig.TLSKeyFile != nil) { server.usesTLS = true; server.certificateFile = listenConfig.TLSCertificateFile; server.privateKeyFile = listenConfig.TLSKeyFile; } server.numberOfThreads = [OFSystemInfo numberOfCPUs] + 1; server.delegate = self; of_log(@"Starting server on host %@ port %" PRIu16, listenConfig.host, listenConfig.port); [server start]; } - (void)server: (OFHTTPServer *)server didReceiveRequest: (OFHTTPRequest *)request requestBody: (OFStream *)requestBody response: (OFHTTPResponse *)response { OFString *path = request.URL.path; of_log(@"Request: %@", request); for (OFPair OF_GENERIC(OFString *, id <Module>) *module in _modules) if ([path hasPrefix: module.firstObject]) if ([module.secondObject handleRequest: request requestBody: requestBody response: response]) return; } - (bool)server: (OFHTTPServer *)server didReceiveExceptionOnListeningSocket: (id)exception { of_log(@"Exception on listening socket: %@", exception); return true; } @end |
Changes to StaticModule.m.
︙ | ︙ | |||
67 68 69 70 71 72 73 | { [_file release]; [_response release]; [super dealloc]; } | | | | | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | { [_file release]; [_response release]; [super dealloc]; } - (OFData *)stream: (OFStream *)stream didWriteData: (OFData *)data bytesWritten: (size_t)bytesWritten exception: (id)exception { if (exception != nil || _file.atEndOfStream) return nil; return readData(_file); } @end @implementation StaticModule - (void)dealloc { [_root release]; [super dealloc]; } - (void)parseConfig: (OFXMLElement *)config { OFMutableDictionary OF_GENERIC(OFString *, OFString *) *MIMETypes; _root = [[config elementForName: @"root"].stringValue copy]; if (_root == nil) { [of_stderr writeString: @"Error parsing config: No <root/> element!"]; [OFApplication terminateWithStatus: 1]; } MIMETypes = [OFMutableDictionary dictionary]; for (OFXMLElement *MIMEType in [config elementsForName: @"mime-type"]) { OFString *extension = [MIMEType attributeForName: @"extension"].stringValue; OFString *type = [MIMEType attributeForName: @"type"].stringValue; if (extension == nil) { [of_stderr writeString: @"Error parsing config: " @"<mime-type/> has no extension attribute!"]; [OFApplication terminateWithStatus: 1]; } |
︙ | ︙ | |||
129 130 131 132 133 134 135 | _MIMETypes = [MIMETypes mutableCopy]; } - (bool)handleRequest: (OFHTTPRequest *)request requestBody: (OFStream *)requestBody response: (OFHTTPResponse *)response { | | | | | | | | | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | _MIMETypes = [MIMETypes mutableCopy]; } - (bool)handleRequest: (OFHTTPRequest *)request requestBody: (OFStream *)requestBody response: (OFHTTPResponse *)response { OFURL *URL = request.URL.URLByStandardizingPath; OFString *path = URL.path; OFMutableDictionary *headers = [OFMutableDictionary dictionary]; OFFileManager *fileManager; bool firstComponent = true; OFString *MIMEType; StaticModule_FileSender *fileSender; for (OFString *component in URL.pathComponents) { if (firstComponent && component.length != 0) return false; if ([component isEqual: @"."] || [component isEqual: @".."]) return false; firstComponent = false; } /* TODO: Properly handle for OSes that do not use UNIX paths */ if (![path hasPrefix: @"/"]) return false; path = [_root stringByAppendingString: path]; fileManager = [OFFileManager defaultManager]; if ([fileManager directoryExistsAtPath: path]) path = [path stringByAppendingPathComponent: @"index.html"]; if (![fileManager fileExistsAtPath: path]) { response.statusCode = 404; return false; } MIMEType = [_MIMETypes objectForKey: path.pathExtension]; if (MIMEType == nil) MIMEType = [_MIMETypes objectForKey: @""]; if (MIMEType != nil) [headers setObject: MIMEType forKey: @"Content-Type"]; fileSender = [[[StaticModule_FileSender alloc] init] autorelease]; fileSender->_file = [[OFFile alloc] initWithPath: path mode: @"r"]; fileSender->_response = [response retain]; response.statusCode = 200; response.headers = headers; response.delegate = fileSender; [response asyncWriteData: readData(fileSender->_file)]; return true; } @end StaticModule * init_plugin(void) { return [[[StaticModule alloc] init] autorelease]; } |