| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent c4312fe commit 85e6c29
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | #include "HTTPNode.hpp" | |
| 2 | + #include "HTTPSServerConstants.hpp" | ||
| 2 | 3 | ||
| 3 | 4 | namespace httpsserver { | |
| 4 | 5 | ||
@@ -7,63 +8,47 @@ namespace httpsserver { | |||
| 7 | 8 | _tag(tag), | |
| 8 | 9 | _nodeType(nodeType) { | |
| 9 | 10 | ||
| 10 | - // Create vector for valdiators | ||
| 11 | - _validators = new std::vector<HTTPValidator*>(); | ||
| 12 | - | ||
| 13 | - // Count the parameters | ||
| 14 | - _pathParamCount = 0; | ||
| 11 | + // Count the parameters and store the indices | ||
| 15 | 12 | size_t idx = 0; | |
| 16 | 13 | while((idx = path.find("/*", idx)) != std::string::npos) { | |
| 17 | - _pathParamCount+=1; | ||
| 18 | - // If we don't do this, the same index will be found again... and again... and again... | ||
| 19 | - idx+=1; | ||
| 20 | - }; | ||
| 21 | - | ||
| 22 | - // Check if there are parameters | ||
| 23 | - if (_pathParamCount > 0) { | ||
| 24 | - // If there are parameters, store their indices | ||
| 25 | - _pathParamIdx = new size_t[_pathParamCount]; | ||
| 26 | - for(int i = 0; i < _pathParamCount; i++) { | ||
| 27 | - _pathParamIdx[i] = path.find("/*", i==0 ? 0 : _pathParamIdx[i-1])+1; | ||
| 14 | + // Skip the "/*" | ||
| 15 | + idx+=2; | ||
| 16 | + // Assure that we have either /* at the URL's end or /*/ somewhere in between | ||
| 17 | + if (idx == path.size() || path[idx] == '/') { | ||
| 18 | + _pathParamIdx.push_back(idx - 1); | ||
| 28 | 19 | } | |
| 29 | - } else { | ||
| 30 | - _pathParamIdx = NULL; | ||
| 31 | - } | ||
| 20 | + }; | ||
| 32 | 21 | } | |
| 33 | - | ||
| 22 | + | ||
| 34 | 23 | HTTPNode::~HTTPNode() { | |
| 35 | - if (_pathParamIdx != NULL) { | ||
| 36 | - delete[] _pathParamIdx; | ||
| 37 | - } | ||
| 38 | - | ||
| 39 | 24 | // Delete validator references | |
| 40 | - for(std::vector<HTTPValidator*>::iterator validator = _validators->begin(); validator != _validators->end(); ++validator) { | ||
| 25 | + for(std::vector<HTTPValidator*>::iterator validator = _validators.begin(); validator != _validators.end(); ++validator) { | ||
| 41 | 26 | delete *validator; | |
| 42 | 27 | } | |
| 43 | - delete _validators; | ||
| 44 | 28 | } | |
| 45 | 29 | ||
| 46 | 30 | bool HTTPNode::hasPathParameter() { | |
| 47 | - return _pathParamCount > 0; | ||
| 31 | + return !_pathParamIdx.empty(); | ||
| 48 | 32 | } | |
| 49 | 33 | ||
| 50 | - size_t HTTPNode::getParamIdx(uint8_t idx) { | ||
| 51 | - if (idx<_pathParamCount) { | ||
| 34 | + ssize_t HTTPNode::getParamIdx(size_t idx) { | ||
| 35 | + if (idx<_pathParamIdx.size()) { | ||
| 52 | 36 | return _pathParamIdx[idx]; | |
| 53 | 37 | } else { | |
| 54 | 38 | return -1; | |
| 55 | 39 | } | |
| 56 | 40 | } | |
| 57 | 41 | ||
| 58 | 42 | size_t HTTPNode::getPathParamCount() { | |
| 59 | - return _pathParamCount; | ||
| 43 | + return _pathParamIdx.size(); | ||
| 60 | 44 | } | |
| 61 | 45 | ||
| 62 | 46 | void HTTPNode::addPathParamValidator(size_t paramIdx, const HTTPValidationFunction * validator) { | |
| 63 | - _validators->push_back(new HTTPValidator(paramIdx, validator)); | ||
| 47 | + _validators.push_back(new HTTPValidator(paramIdx, validator)); | ||
| 48 | + | ||
| 64 | 49 | } | |
| 65 | 50 | ||
| 66 | 51 | std::vector<HTTPValidator*> * HTTPNode::getValidators() { | |
| 67 | - return _validators; | ||
| 52 | + return &_validators; | ||
| 68 | 53 | } | |
| 69 | 54 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,7 +45,7 @@ class HTTPNode { | |||
| 45 | 45 | ||
| 46 | 46 | bool hasPathParameter(); | |
| 47 | 47 | size_t getPathParamCount(); | |
| 48 | - size_t getParamIdx(uint8_t); | ||
| 48 | + ssize_t getParamIdx(size_t); | ||
| 49 | 49 | ||
| 50 | 50 | std::vector<HTTPValidator*> * getValidators(); | |
| 51 | 51 | ||
@@ -61,9 +61,8 @@ class HTTPNode { | |||
| 61 | 61 | void addPathParamValidator(size_t paramIdx, const HTTPValidationFunction * validator); | |
| 62 | 62 | ||
| 63 | 63 | private: | |
| 64 | - size_t _pathParamCount; | ||
| 65 | - size_t * _pathParamIdx; | ||
| 66 | - std::vector<HTTPValidator*> * _validators; | ||
| 64 | + std::vector<size_t> _pathParamIdx; | ||
| 65 | + std::vector<HTTPValidator*> _validators; | ||
| 67 | 66 | }; | |
| 68 | 67 | ||
| 69 | 68 | } // namespace httpserver | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | #include "ResourceParameters.hpp" | |
| 2 | + #include "HTTPSServerConstants.hpp" | ||
| 2 | 3 | ||
| 3 | 4 | namespace httpsserver { | |
| 4 | 5 | ||
@@ -157,7 +158,7 @@ void ResourceParameters::resetPathParameters() { | |||
| 157 | 158 | } | |
| 158 | 159 | ||
| 159 | 160 | void ResourceParameters::setPathParameter(size_t idx, std::string const &val) { | |
| 160 | - if(idx>=_pathParams.capacity()) { | ||
| 161 | + if(idx>=_pathParams.size()) { | ||
| 161 | 162 | _pathParams.resize(idx + 1); | |
| 162 | 163 | } | |
| 163 | 164 | _pathParams.at(idx) = val; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -35,6 +35,8 @@ void ResourceResolver::resolveNode(const std::string &method, const std::string | |||
| 35 | 35 | ||
| 36 | 36 | // Split URL in resource name and request params. Request params start after an optional '?' | |
| 37 | 37 | size_t reqparamIdx = url.find('?'); | |
| 38 | + // Store this index to stop path parsing there | ||
| 39 | + size_t pathEnd = reqparamIdx != std::string::npos ? reqparamIdx : url.size(); | ||
| 38 | 40 | ||
| 39 | 41 | // If no '?' is contained in url, 0:npos will return the string as it is | |
| 40 | 42 | std::string resourceName = url.substr(0, reqparamIdx); | |
@@ -72,92 +74,69 @@ void ResourceResolver::resolveNode(const std::string &method, const std::string | |||
| 72 | 74 | ||
| 73 | 75 | ||
| 74 | 76 | // Check whether a resource matches | |
| 75 | - for(std::vector<HTTPNode*>::iterator node = _nodes->begin(); node != _nodes->end(); ++node) { | ||
| 77 | + | ||
| 78 | + for(std::vector<HTTPNode*>::iterator itNode = _nodes->begin(); itNode != _nodes->end(); ++itNode) { | ||
| 76 | 79 | params->resetPathParameters(); | |
| 77 | - if ((*node)->_nodeType==nodeType) { | ||
| 80 | + HTTPNode *node = *itNode; | ||
| 81 | + if (node->_nodeType==nodeType) { | ||
| 78 | 82 | if ( | |
| 79 | 83 | // For handler functions, check the method declared with the node | |
| 80 | - ((*node)->_nodeType==HANDLER_CALLBACK && ((ResourceNode*)*node)->_method == method) || | ||
| 84 | + (node->_nodeType==HANDLER_CALLBACK && ((ResourceNode*)node)->_method == method) || | ||
| 81 | 85 | // For websockets, the specification says that GET is the only choice | |
| 82 | - ((*node)->_nodeType==WEBSOCKET && method=="GET") | ||
| 86 | + (node->_nodeType==WEBSOCKET && method=="GET") | ||
| 83 | 87 | ) { | |
| 84 | - const std::string nodepath = ((*node)->_path); | ||
| 85 | - if (!((*node)->hasPathParameter())) { | ||
| 86 | - HTTPS_LOGD("Testing simple match on %s", nodepath.c_str()); | ||
| 87 | - | ||
| 88 | - // Simple matching, the node does not contain any resource parameters | ||
| 89 | - if (nodepath == resourceName) { | ||
| 90 | - resolvedResource.setMatchingNode(*node); | ||
| 91 | - HTTPS_LOGD("It's a match! Path: %s", nodepath.c_str()); | ||
| 92 | - break; | ||
| 93 | - } | ||
| 94 | - } else { | ||
| 95 | - HTTPS_LOGD("Testing parameter match on %s", nodepath.c_str()); | ||
| 96 | - | ||
| 97 | - // Advanced matching, we need to align the /?/ parts. | ||
| 98 | - bool didMatch = true; | ||
| 99 | - size_t urlIdx = 0; // Pointer how far the input url is processed | ||
| 100 | - size_t nodeIdx = 0; // Pointer how far the node url is processed | ||
| 101 | - for (int pIdx = 0; didMatch && pIdx < (*node)->getPathParamCount(); pIdx++) { | ||
| 102 | - size_t pOffset = (*node)->getParamIdx(pIdx); | ||
| 103 | - | ||
| 104 | - // First step: Check static part | ||
| 105 | - size_t staticLength = pOffset-nodeIdx; | ||
| 106 | - if (nodepath.substr(nodeIdx, staticLength).compare(resourceName.substr(urlIdx, staticLength))!=0) { | ||
| 107 | - // static part did not match | ||
| 108 | - didMatch = false; | ||
| 109 | - HTTPS_LOGD("No match on static part %d", pIdx); | ||
| 110 | - } else { | ||
| 111 | - // static part did match, increase pointers | ||
| 112 | - nodeIdx += staticLength + 1; // +1 to take care of the '*' placeholder. | ||
| 113 | - urlIdx += staticLength; // The pointer should now point to the begin of the static part | ||
| 114 | - | ||
| 115 | - // Second step: Grab the parameter value | ||
| 116 | - if (nodeIdx == nodepath.length()) { | ||
| 117 | - // Easy case: parse until end of string | ||
| 118 | - params->setPathParameter(pIdx, urlDecode(resourceName.substr(urlIdx))); | ||
| 119 | - } else { | ||
| 120 | - // parse until first char after the placeholder | ||
| 121 | - char terminatorChar = nodepath[nodeIdx]; | ||
| 122 | - size_t terminatorPosition = resourceName.find(terminatorChar, urlIdx); | ||
| 123 | - if (terminatorPosition != std::string::npos) { | ||
| 124 | - // We actually found the terminator | ||
| 125 | - size_t dynamicLength = terminatorPosition-urlIdx; | ||
| 126 | - params->setPathParameter(pIdx, urlDecode(resourceName.substr(urlIdx, dynamicLength))); | ||
| 127 | - urlIdx = urlIdx + dynamicLength; | ||
| 128 | - } else { | ||
| 129 | - // We did not find the terminator | ||
| 130 | - didMatch = false; | ||
| 131 | - HTTPS_LOGD("No match on dynamic part %d", pIdx); | ||
| 132 | - } | ||
| 133 | - } | ||
| 134 | - } // static part did match | ||
| 135 | - } // placeholder loop | ||
| 136 | - | ||
| 137 | - // If there is some final static part to process | ||
| 138 | - if (didMatch && nodeIdx < nodepath.length()) { | ||
| 139 | - size_t staticLength = nodepath.length()-nodeIdx; | ||
| 140 | - if (nodepath.substr(nodeIdx, staticLength).compare(url.substr(urlIdx, staticLength))!=0) { | ||
| 141 | - didMatch = false; | ||
| 142 | - HTTPS_LOGD("No match, final static part did not match"); | ||
| 88 | + HTTPS_LOGD("Testing route %s", node->_path.c_str()); | ||
| 89 | + bool match = true; | ||
| 90 | + size_t paramCount = node->getPathParamCount(); | ||
| 91 | + // indices in input and pattern | ||
| 92 | + size_t inputIdx = 0, pathIdx = 0; | ||
| 93 | + HTTPS_LOGD("(INIT) inputIdx: %d, pathIdx: %d, pathEnd: %d, path: %s, url: %s", | ||
| 94 | + inputIdx, pathIdx, pathEnd, node->_path.c_str(), url.c_str()); | ||
| 95 | + | ||
| 96 | + for (size_t paramIdx = 0; match && paramIdx < paramCount; paramIdx += 1) { | ||
| 97 | + HTTPS_LOGD("(LOOP) inputIdx: %d, pathIdx: %d, pathEnd: %d, path: %s, url: %s", | ||
| 98 | + inputIdx, pathIdx, pathEnd, node->_path.c_str(), url.c_str()); | ||
| 99 | + // Test static path before the parameter | ||
| 100 | + size_t paramPos = node->getParamIdx(paramIdx); | ||
| 101 | + size_t staticLength = paramPos - pathIdx; | ||
| 102 | + match &= url.substr(inputIdx, staticLength) == node->_path.substr(pathIdx, staticLength); | ||
| 103 | + inputIdx += staticLength; | ||
| 104 | + pathIdx += staticLength; | ||
| 105 | + | ||
| 106 | + // Extract parameter value | ||
| 107 | + if (match) { | ||
| 108 | + size_t paramEnd = url.find('/', inputIdx); | ||
| 109 | + if (paramEnd == std::string::npos && inputIdx <= pathEnd) { | ||
| 110 | + // Consume the remaining input (might be "" for the last param) | ||
| 111 | + paramEnd = pathEnd; | ||
| 112 | + } | ||
| 113 | + if (paramEnd != std::string::npos) { | ||
| 114 | + size_t paramLength = paramEnd - inputIdx; | ||
| 115 | + params->setPathParameter(paramIdx, urlDecode(url.substr(inputIdx, paramLength))); | ||
| 116 | + pathIdx += 1; | ||
| 117 | + inputIdx += paramLength; | ||
| 143 | 118 | } else { | |
| 144 | - urlIdx += staticLength; | ||
| 145 | - // If there is some string remaining in the url that did not match | ||
| 146 | - if (urlIdx < resourceName.length()) { | ||
| 147 | - didMatch = false; | ||
| 148 | - HTTPS_LOGD("No match, URL is longer than final static part"); | ||
| 149 | - } | ||
| 119 | + match = false; | ||
| 120 | + HTTPS_LOGD("(LOOP) No match on param part"); | ||
| 150 | 121 | } | |
| 122 | + } else { | ||
| 123 | + HTTPS_LOGD("(LOOP) No match on static part"); | ||
| 151 | 124 | } | |
| 152 | - | ||
| 153 | - // Every check worked, so the full url matches and the params are set | ||
| 154 | - if (didMatch) { | ||
| 155 | - resolvedResource.setMatchingNode(*node); | ||
| 156 | - HTTPS_LOGD("It's a match!"); | ||
| 157 | - break; | ||
| 158 | - } | ||
| 159 | - | ||
| 160 | - } // static/dynamic url | ||
| 125 | + } | ||
| 126 | + HTTPS_LOGD("(STTC) inputIdx: %d, pathIdx: %d, pathEnd: %d, path: %s, url: %s", | ||
| 127 | + inputIdx, pathIdx, pathEnd, node->_path.c_str(), url.c_str()); | ||
| 128 | + // Test static path after the parameter (up to pathEnd) | ||
| 129 | + if (match) { | ||
| 130 | + match = url.substr(inputIdx, pathEnd - inputIdx)==node->_path.substr(pathIdx); | ||
| 131 | + } | ||
| 132 | + HTTPS_LOGD("(END ) inputIdx: %d, pathIdx: %d, pathEnd: %d, path: %s, url: %s", | ||
| 133 | + inputIdx, pathIdx, pathEnd, node->_path.c_str(), url.c_str()); | ||
| 134 | + | ||
| 135 | + if (match) { | ||
| 136 | + resolvedResource.setMatchingNode(node); | ||
| 137 | + HTTPS_LOGD("It's a match!"); | ||
| 138 | + break; | ||
| 139 | + } | ||
| 161 | 140 | } // method check | |
| 162 | 141 | } // node type check | |
| 163 | 142 | } // resource node for loop | |
| Back | FazBrowse Home | New Git URL |
0 commit comments