123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- #include "main.h"
- #include "helpers.h"
- #include "callback.h"
- /////////////////////////////////////////////////////////////////////////////
- static void _SetCORSResponseHeaders(struct _u_response * response, bool bAllowCredentials = true);
- /////////////////////////////////////////////////////////////////////////////
- #define _SIG_BLOCK(s) pthread_sigmask(SIG_BLOCK, (s), NULL)
- #define _SIG_UNBLOCK(s) pthread_sigmask(SIG_UNBLOCK, (s), NULL)
- /////////////////////////////////////////////////////////////////////////////
- // FileBodyResponseCallback (serves static files)
- int FileBodyResponseCallback(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- UNUSED(request);
- LPFILEREQUEST pfr = (LPFILEREQUEST)user_data;
- if(pfr)
- {
- FILE *pf = fopen(pfr->strFilename.c_str(), "rb");
- if(pf)
- {
- size_t nSize = GetFileSize(pf);
- char *pszContent = (char*)malloc(nSize + 1);
- nSize = fread(pszContent, 1, nSize, pf);
- fclose(pf);
- pszContent[nSize] = '\0';
- _SetCORSResponseHeaders(response);
- ulfius_add_header_to_response(response, "Content-Type", pfr->strContentType.c_str());
- ulfius_set_binary_body_response(response, 200, pszContent, nSize);
- free(pszContent);
- return U_CALLBACK_CONTINUE;
- }
- else
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 404);
- }
- }
- else
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- }
- return U_CALLBACK_CONTINUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // GetShmPostResponseCallback_M - getshm - POST Request, returns a linear map
- int GetShmPostResponseCallback_M(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- LPCSHM_REQUEST_PARAMS psrp = (LPCSHM_REQUEST_PARAMS)user_data;
- if(!psrp || !psrp->pMap || !psrp->pszUuid)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_CONTINUE;
- }
- CRestVarTable &map = *psrp->pMap;
- json_error_t jErr;
- CJson_t jtRequ(ulfius_get_json_body_request(request, &jErr)); // new reference!
- CJson_t jtUuid(json_string(psrp->pszUuid)); // new reference!
- if(jtRequ.IsValid())
- {
- CJson_t jtResponse(json_object()); // new reference!
- CJson_t jtArrValues(json_array()); // new reference!
- json_object_set(jtResponse, "uuid", jtUuid);
- if(jtRequ.IsArray())
- {
- json_object_set(jtResponse, "request", jtRequ);
- size_t nIndex;
- json_t *pjtEle;
- json_array_foreach(jtRequ, nIndex, pjtEle)
- {
- CJson_t jtPath(json_object_get(pjtEle, "path"), false); // borrowed reference!
- if(!jtPath.IsValid())
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 400);
- return U_CALLBACK_CONTINUE;
- }
- const char *pszPath = json_string_value(jtPath);
- CRest *pRest = map.Find(pszPath);
- if(!pRest)
- {
- CJson_t jtStatus(CRest::CreateStatusObject((int)nIndex, -1, "Invalid path!", pszPath));
- json_array_append(jtArrValues, jtStatus);
- }
- else
- {
- sigset_t sset;
- ::sigfillset(&sset);
- _SIG_BLOCK(&sset);
- pRest->GetValue((int)nIndex, jtArrValues); // new reference!
- _SIG_UNBLOCK(&sset);
- }
- }
- json_object_set(jtResponse, "response", jtArrValues);
- _SetCORSResponseHeaders(response);
- ulfius_set_json_body_response(response, 200, jtResponse);
- }
- else if(jtRequ.IsObject())
- {
- CJson_t jtArrReq(json_array()); // new reference!
- json_array_append(jtArrReq, jtRequ);
- json_object_set(jtResponse, "request", jtArrReq);
- CJson_t jtPath(json_object_get(jtRequ, "path"), false); // borrowed reference!
- if(!jtPath.IsValid())
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 400);
- return U_CALLBACK_CONTINUE;
- }
- const char *pszPath = json_string_value(jtPath);
- CRest *pRest = map.Find(pszPath);
- if(!pRest)
- {
- CJson_t jtStatus(CRest::CreateStatusObject(0, -1, "Invalid path!", pszPath));
- json_array_append(jtArrValues, jtStatus);
- }
- else
- {
- sigset_t sset;
- ::sigfillset(&sset);
- _SIG_BLOCK(&sset);
- pRest->GetValue(0, jtArrValues); // new reference!
- _SIG_UNBLOCK(&sset);
- }
- json_object_set(jtResponse, "response", jtArrValues);
- _SetCORSResponseHeaders(response);
- ulfius_set_json_body_response(response, 200, jtResponse);
- }
- else
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 400);
- return U_CALLBACK_CONTINUE;
- }
- }
- else
- {
- fprintf(stderr, "%s\n", jErr.text);
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- }
- return U_CALLBACK_CONTINUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // GetShmPostResponseCallback_O - getshm - POST Request, returns a structured object
- int GetShmPostResponseCallback_O(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- LPCSHM_REQUEST_PARAMS psrp = (LPCSHM_REQUEST_PARAMS)user_data;
- if(!psrp || !psrp->pMap || !psrp->pszUuid)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_CONTINUE;
- }
- CRestVarTable &map = *psrp->pMap;
- json_error_t jErr;
- CJson_t jtRequ(ulfius_get_json_body_request(request, &jErr)); // new reference!
- CJson_t jtUuid(json_string(psrp->pszUuid)); // new reference!
- if(jtRequ)
- {
- CJson_t jtPath(json_object_get(jtRequ, "path"), false); // borrowed reference!
- if(!jtPath)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_CONTINUE;
- }
- const char *pszPath = json_string_value(jtPath);
- CRest *pRest = map.Find(pszPath);
- if(!pRest)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 404);
- return U_CALLBACK_CONTINUE;
- }
- sigset_t sset;
- ::sigfillset(&sset);
- _SIG_BLOCK(&sset);
- CJson_t jtVal(pRest->GetValue(0)); // new reference!
- _SIG_UNBLOCK(&sset);
- if(jtVal)
- {
- CJson_t jtObj(json_object()); // new reference!
- json_object_set(jtObj, "request", jtRequ);
- json_object_set(jtObj, "response", jtVal);
- json_object_set(jtObj, "uuid", jtUuid);
- _SetCORSResponseHeaders(response);
- ulfius_set_json_body_response(response, 200, jtObj);
- }
- else
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- }
- }
- else
- {
- fprintf(stderr, "%s\n", jErr.text);
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- }
- return U_CALLBACK_CONTINUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // SetShmPostResponseCallback - setshm - POST Request
- int SetShmPostResponseCallback(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- LPCSHM_REQUEST_PARAMS psrp = (LPCSHM_REQUEST_PARAMS)user_data;
- if(!psrp || !psrp->pMap || !psrp->pszUuid)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_CONTINUE;
- }
- CRestVarTable &map = *psrp->pMap;
- json_error_t jErr;
- CJson_t jtRequ(ulfius_get_json_body_request(request, &jErr)); // new reference!
- CJson_t jtUuid(json_string(psrp->pszUuid)); // new reference!
- if(jtRequ.IsValid())
- {
- CJson_t jtResponse(json_object()); // new reference!
- CJson_t jtArrStatus(json_array()); // new reference!
- json_object_set(jtResponse, "uuid", jtUuid);
- json_object_set(jtResponse, "response", jtArrStatus);
- if(jtRequ.IsArray())
- {
- json_object_set(jtResponse, "request", jtRequ);
- size_t nIndex;
- json_t *pjtEle;
- json_array_foreach(jtRequ, nIndex, pjtEle)
- {
- CJson_t jtPath(json_object_get(pjtEle, "path"), false); // borrowed reference!
- CJson_t jtVal(json_object_get(pjtEle, "value"), false); // borrowed reference!
- if(!jtPath.IsValid() || !jtVal.IsValid())
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 400);
- return U_CALLBACK_CONTINUE;
- }
- const char *pszPath = json_string_value(jtPath);
- CRest *pRest = map.Find(pszPath);
- if(!pRest)
- {
- CJson_t jtStatus(CRest::CreateStatusObject((int)nIndex, -1, "Invalid path!", pszPath));
- json_array_append(jtArrStatus, jtStatus);
- }
- else
- {
- sigset_t sset;
- ::sigfillset(&sset);
- _SIG_BLOCK(&sset);
- CJson_t jtStatus(pRest->SetValue((int)nIndex, jtVal)); // new reference!
- _SIG_UNBLOCK(&sset);
- json_array_append(jtArrStatus, jtStatus);
- }
- }
- _SetCORSResponseHeaders(response);
- ulfius_set_json_body_response(response, 200, jtResponse);
- }
- else if(jtRequ.IsObject())
- {
- CJson_t jtArrReq(json_array()); // new reference!
- json_array_append(jtArrReq, jtRequ);
- json_object_set(jtResponse, "request", jtArrReq);
- CJson_t jtPath(json_object_get(jtRequ, "path"), false); // borrowed reference!
- CJson_t jtVal(json_object_get(jtRequ, "value"), false); // borrowed reference!
- if(!jtPath.IsValid() || !jtVal.IsValid())
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_CONTINUE;
- }
- const char *pszPath = json_string_value(jtPath);
- CRest *pRest = map.Find(pszPath);
- if(!pRest)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 404);
- return U_CALLBACK_CONTINUE;
- }
- sigset_t sset;
- ::sigfillset(&sset);
- _SIG_BLOCK(&sset);
- CJson_t jtStatus(pRest->SetValue(0, jtVal)); // new reference!
- _SIG_UNBLOCK(&sset);
- json_array_append(jtArrStatus, jtStatus);
- _SetCORSResponseHeaders(response);
- ulfius_set_json_body_response(response, 200, jtResponse);
- }
- else
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 400);
- return U_CALLBACK_CONTINUE;
- }
- }
- else
- {
- fprintf(stderr, "%s\n", jErr.text);
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- }
- return U_CALLBACK_CONTINUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // GetShmGetResponseCallback - getshm - GET Request
- int GetShmGetResponseCallback(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- static size_t nPrefixLen = strlen(GET_SHM_PREFIX);
- LPCSHM_REQUEST_PARAMS psrp = (LPCSHM_REQUEST_PARAMS)user_data;
- if(!psrp || !psrp->pMap || !psrp->pszUuid)
- {
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_COMPLETE;
- }
- CJson_t jtUuid(json_string(psrp->pszUuid)); // new reference!
- const char *pszPath = request->http_url;
- CURL *hUrl = NULL;
- char *pszCUrl = NULL, *pszUrlParams = NULL;
- if(!pszPath || !*pszPath || strlen(pszPath) == nPrefixLen)
- pszPath = "/";
- else
- {
- hUrl = curl_easy_init();
- pszPath += nPrefixLen;
- pszCUrl = curl_easy_unescape(hUrl, pszPath, 0, NULL);
- pszPath = pszCUrl;
- pszUrlParams = strchr(pszCUrl, '?');
- if(pszUrlParams)
- {
- *pszUrlParams++ = '\0';
- /* char **ppRet;
- split_string(pszUrlParams, "&", &ppRet);
- free_string_array(ppRet);*/
- }
- }
- CRestVarTable &map = *psrp->pMap;
- CRest *pRest = map.Find(pszPath);
- if(!pRest)
- {
- if(pszCUrl)
- curl_free(pszCUrl);
- if(hUrl)
- curl_easy_cleanup(hUrl);
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 404);
- return U_CALLBACK_COMPLETE;
- }
- sigset_t sset;
- ::sigfillset(&sset);
- _SIG_BLOCK(&sset);
- CJson_t jtVal(pRest->GetValue(0)); // new reference!
- _SIG_UNBLOCK(&sset);
- if(jtVal.IsValid())
- {
- CJson_t jtRequ(json_object()); // new reference!
- CJson_t jtPath(json_string(pszPath));
- json_object_set(jtRequ, "path", jtPath);
- CJson_t jtObj(json_object()); // new reference!
- json_object_set(jtObj, "request", jtRequ);
- json_object_set(jtObj, "response", jtVal);
- json_object_set(jtObj, "uuid", jtUuid);
- _SetCORSResponseHeaders(response);
- ulfius_add_header_to_response(response, "Content-Disposition", "attachment; filename=\"shm.json\"");
- ulfius_set_json_body_response(response, 200, jtObj);
- }
- else
- {
- if(pszCUrl)
- curl_free(pszCUrl);
- if(hUrl)
- curl_easy_cleanup(hUrl);
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 500);
- return U_CALLBACK_COMPLETE;
- }
- if(pszCUrl)
- curl_free(pszCUrl);
- if(hUrl)
- curl_easy_cleanup(hUrl);
- return U_CALLBACK_CONTINUE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // OptionsResponseCallback - OPTIONS Request (CORS preflight ...)
- int OptionsResponseCallback(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- UNUSED(user_data);
- const char *pszHeaders = u_map_get_case(request->map_header, "Access-Control-Request-Headers");
- if(!pszHeaders)
- pszHeaders = "Content-Type";
- ulfius_add_header_to_response(response, "Allow", "POST, GET, OPTIONS");
- ulfius_add_header_to_response(response, "Access-Control-Allow-Methods", "POST, GET, OPTIONS");
- ulfius_add_header_to_response(response, "Access-Control-Allow-Headers", pszHeaders);
- _SetCORSResponseHeaders(response);
- ulfius_set_empty_body_response(response, 200); // Ok
- return U_CALLBACK_COMPLETE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // NotAllowedResponseCallback
- int NotAllowedResponseCallback(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- UNUSED(request);
- UNUSED(user_data);
- ulfius_set_empty_body_response(response, 405); // Method Not Allowed
- return U_CALLBACK_COMPLETE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // NotImplementedResponseCallback
- int NotImplementedResponseCallback(const struct _u_request * request, struct _u_response * response, void * user_data)
- {
- UNUSED(request);
- UNUSED(user_data);
- ulfius_set_empty_body_response(response, 501); // Not Implemented
- return U_CALLBACK_COMPLETE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // _SetCORSResponseHeaders
- static void _SetCORSResponseHeaders(struct _u_response * response, bool bAllowCredentials)
- {
- ulfius_add_header_to_response(response, "Access-Control-Allow-Origin", "*");
- if(bAllowCredentials)
- ulfius_add_header_to_response(response, "Access-Control-Allow-Credentials", "true");
- }
|