Recent Entries 10
- pattern minor 112d agoCurl-based REST client library (round 2)This is a second iteration on an earlier review - cURL based REST client library I have done some refactoring to split out the REST HTTP response into it's own class from what was in the previous review and implement. You might find it useful to read the library's README file before performing this review for further background and usage examples, which I have omitted here for brevity and to allow the question to focus on the code. I am only reviewing the single REST call portion of the library here. I have also opened a separate review to cover the `curl_multi_*` based functionality for performing multiple requests in parallel. RestClient class ``` validateAction($action); $this->curlSetup(); $this->setRequestUrl($action); curl_setopt($this->curl, CURLOPT_HTTPGET, true); // execute call. Can throw \Exception. $this->curlExec(); return $this->response; } /** * Method to exexute POST on server * * @param mixed $action * @param mixed $data * @return CurlHttpResponse * @throws \InvalidArgumentException * @throws \Exception */ public function post($action, $data) { $this->validateAction($action); $this->validateData($data); $this->curlSetup(); $this->setRequestUrl($action); $this->setRequestData($data); curl_setopt($this->curl, CURLOPT_POST, true); // execute call. Can throw \Exception. $this->curlExec(); return $this->response; } /** * Method to execute PUT on server * * @param string $action * @param mixed $data * @return CurlHttpResponse * @throws \InvalidArgumentException * @throws \Exception */ public function put($action, $data) { $this->validateAction($action); $this->validateData($data); $this->curlSetup(); $this->setRequestUrl($action); $this->setRequestData($data); curl_setopt($thi
- pattern minor 112d agocURL based REST client libraryI have recently refactored a REST client library and was hoping to get review for both the class itself and the unit tests that cover it. This code is developed against PHP 7.1, but tested against PHP 5.6, 7.0 7.1, HipHop VM, and PHP nightly builds. The full library can be seen on GitHub RestClient.php ``` validateAction($action); $this->curlSetup(); $this->setRequestUrl($action); curl_setopt($this->curl, CURLOPT_HTTPGET, true); // execute call. Can throw \Exception. $this->curlExec(); return $this; } /** * Method to exexute POST on server * * @param mixed $action * @param mixed $data * @return RestClient * @throws \InvalidArgumentException * @throws \Exception */ public function post($action = null, $data = null) { $this->validateAction($action); $this->validateData($data); $this->curlSetup(); $this->setRequestUrl($action); $this->setRequestData($data); curl_setopt($this->curl, CURLOPT_POST, true); // execute call. Can throw \Exception. $this->curlExec(); return $this; } /** * Method to execute PUT on server * * @param string $action * @param mixed $data * @return RestClient * @throws \InvalidArgumentException * @throws \Exception */ public function put($action = null, $data = null) { $this->validateAction($action); $this->validateData($data); $this->curlSetup(); $this->setRequestUrl($action); $this->setRequestData($data); curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, 'PUT'); // execute call. Can throw \Exception. $this->curlExec(); return $this; } /** * Method to execute DELETE on server * * @param string $action * @return RestClient * @throws \InvalidArgumentException * @throws \Exception */ public function dele
- pattern minor 112d agoC++ Wrapper for cURL: Multithreading and serializing asynchronous opsI did this library to help me from one of my projects and decided to publish it on GitHub hoping people might find it useful, convenient and easy to use in their projects too. It's a header-only library. The library design is inspired by some popular Java code conventions, like naming of classes and the popular usage of chaining call of methods. As of now, there are only two HTTP methods I made from `CppUrl` class, which are the `GET` and `POST` with the two corresponding "fetch" functions to execute it either on main thread, or on another thread namely: `execute()` (synchronous) and `async()` (asynchronous). I haven't really tested this on some complicated scenarios so if I may ask, what could probably go wrong here? I could smell some data corruption or some deadlocks when this has been used on an intensive and complicated task, but it might just me. I want the user of this library to type as less as possible of code. So, what do you think of using `std::map` as a function parameter for passing files on a `POST` method? Is it suitable (considering the context)? If not, can you suggest another constructive and simpler way? ``` class CppUrl { using ResponseCallback = std::function; public: class MissingHttpMethodException : std::exception { public: std::string what() { return "No HTTP method used"; } }; CppUrl() : task(nullptr) { if (curlInstanceCount == 0) { curl_global_init(CURL_GLOBAL_ALL); } handle = curl_easy_init(); if (handle) { curlInstanceCount++; } } CppUrl(const CppUrl&) = delete; CppUrl& operator= (CppUrl const&); ~CppUrl() { curlInstanceCount--; curl_easy_cleanup(handle); cleanTask(); handle = nullptr; // busy = false; }); return *this; } /** * Perform a request with a POST method * @param const std::string &url: URL to be requested * @param s
- pattern minor 112d agoPool of curl handlesI am trying to write a simple reusable pool of curl handles. I found this wonderful implementation of the blocking queue. The pool itself looks like this: ``` class curl_pool { private: int m_size; queue m_queue; CURL **m_handles; public: class connection { friend class curl_pool; private: curl_pool &m_pool; int m_index; connection(curl_pool &pool, int index) : m_pool(pool), m_index(index) {} public: connection(connection&& that) : m_pool(that.m_pool), m_index(that.m_index) {} CURL *handle() const { return m_pool.m_handles[m_index]; } void release() { m_pool.m_queue.push(m_index); } virtual ~connection() { release(); } }; connection open() { return connection(*this, m_queue.pop()); } curl_pool(const std::string &root_cert, int size) : m_size(size) { curl_global_init(CURL_GLOBAL_DEFAULT); m_handles = new CURL*[m_size]; for (int i = 0; i < m_size; i++) { CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true); curl_easy_setopt(curl, CURLOPT_CAINFO, root_cert.c_str()); curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L); m_handles[i] = curl; m_queue.push(i); } } virtual ~curl_pool() { for (int i = 0; i < m_size; i++) { curl_easy_cleanup(m_handles[i]); } delete m_handles; curl_global_cleanup(); } }; ``` This is the intended use: ``` { curl_pool::connection c = pool.open(); CURL *curl = c.handle(); curl_easy_setopt(curl, CURLOPT_URL, "https://www.***.com/"); CURLcode res = curl_easy_perform(curl); stream << "Status code: " << res; } ``` I am not a C++ person at all, so I am certain there are a lot of things to
- pattern minor 112d agoSending email using libcurlI developed a function to send email based on this. Does this code have problems? Also, I'm not sure if this code is thread-safe because of the global `payloadText` variable. ``` #include #include static std::string payloadText[11]; std::string dateTimeNow(); std::string generateMessageId(); void setPayloadText(const std::string &to, const std::string &from, const std::string &cc, const std::string &nameFrom, const std::string &subject, const std::string &body) { payloadText[ 0] = "Date: " + dateTimeNow(); payloadText[ 1] = "To: \r\n"; payloadText[ 2] = "From: (" + nameFrom + ")\r\n"; payloadText[ 3] = "Cc: (" + nameFrom + ")\r\n"; payloadText[ 4] = "Message-ID: \r\n"; payloadText[ 5] = "Subject: " + subject + "\r\n"; payloadText[ 6] = "\r\n"; payloadText[ 7] = body + "\r\n"; payloadText[ 8] = "\r\n"; payloadText[ 9] = "\r\n"; // "It could be a lot of lines, could be MIME encoded, whatever.\r\n"; payloadText[10] = "\r\n"; // "Check RFC5322.\r\n"; } std::string dateTimeNow() { static const char *DAY_NAMES [] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; const int RFC1123_TIME_LEN = 29; time_t t; struct tm tm; std::string ret; ret.resize(RFC1123_TIME_LEN); time(&t); gmtime_s(&tm, &t); strftime(&ret[0], RFC1123_TIME_LEN + 1, "---, %d --- %Y %H:%M:%S GMT", &tm); memcpy(&ret[0], DAY_NAMES [tm.tm_wday], 3); memcpy(&ret[8], MONTH_NAMES[tm.tm_mon], 3); return ret; } std::string generateMessageId() { const int MESSAGE_ID_LEN = 37; time_t t; struct tm tm; std::string ret; ret.resize(15); time(&t); gmtime_s(&tm, &t); strftime(const_cast(ret.c_str()), MESSAGE_ID_LEN, "%Y%m%d%H%
- pattern minor 112d agocalloc, malloc, free and realloc wrappers to store the size being allocatedI'm currently building a node.js addon for libcurl. Right now I'm trying to correctly use `v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory` to update v8 on the amount of memory being allocated by libcurl, and to do that I need to wrap the above mentioned functions that libcurl uses, using `curl_global_init_mem()`. I saw the following code being used here that basically does the same thing, but for another lib. I currently have the following code (almost identical to the one above): ``` struct MemWrapper { size_t size; double data; }; #define MEMWRAPPER_SIZE offsetof( MemWrapper, data ) inline void* MemWrapperToClient( MemWrapper* memWrapper ) { return static_cast( reinterpret_cast( memWrapper ) + MEMWRAPPER_SIZE ); } inline MemWrapper* ClientToMemWrapper( void* client ) { return reinterpret_cast( static_cast( client ) - MEMWRAPPER_SIZE ); } void AdjustMem( ssize_t diff ) { Nan::AdjustExternalMemory( static_cast( diff ) ); } void* MallocCallback( size_t size ) { size_t totalSize = size + MEMWRAPPER_SIZE; MemWrapper* mem = static_cast( malloc( totalSize ) ); if ( !mem ) return NULL; mem->size = size; AdjustMem( totalSize ); return MemWrapperToClient( mem ); } void FreeCallback( void* p ) { if ( !p ) return; MemWrapper* mem = ClientToMemWrapper( p ); ssize_t totalSize = mem->size + MEMWRAPPER_SIZE; AdjustMem( -totalSize ); free( mem ); } void* ReallocCallback( void* ptr, size_t size ) { if ( !ptr ) return MallocCallback( size ); MemWrapper* mem1 = ClientToMemWrapper( ptr ); ssize_t oldSize = mem1->size; MemWrapper* mem2 = static_cast( realloc( mem1, size + MEMWRAPPER_SIZE ) ); if ( !mem2 ) return NULL; mem2->size = size; AdjustMem( ssize_t( size ) - oldSize ); return MemWrapperToClient( mem2 ); } char* StrdupCallback( const char* str ) { size_t size = strlen( str ) + 1; char* res = static_cast( MallocCallback( size ) ); if ( res ) memc
- pattern minor 112d agoSimple load testing script in bashHere's the code ``` max="$1" date echo "url: $2 rate: $max calls / second" START=$(date +%s); get () { curl -s -v "$1" 2>&1 | tr '\r\n' '\\n' | awk -v date="$(date +'%r')" '{print $0"\n-----", date}' >> /tmp/perf-test.log } while true do echo $(($(date +%s) - START)) | awk '{print int($1/60)":"int($1%60)}' sleep 1 for i in `seq 1 $max` do get $2 & done done ``` This can be run as `sh load-test.sh 20 "http://api.myserver.com/get_info"` Please suggest if you think there's a way to take in multiple `curl` options.
- pattern minor 112d agoSending an SMS message in CRecently I've been fiddling with the idea of sending a text message using C. Looking at a few options, I thought that using libcurl to send an SMTP email using TLS for some security would be the best and easiest option. Here's what I would like reviewed: - Method: Is there a better/easier way I could be sending an SMS? - Security: Is my current security enough? How could I add more security to make sure my authentication details aren't being snooped on? - SMS Format: Is there a way I could format my payload to look more like what it would if I sent it off using a normal email client? The normal email client sends something that looks like the image on the left, with my first name being blacked out; the image on the right is what it looks like sent from my program with my email being censored. - Conversations: With my program, a new conversation is generated each time an SMS is sent, with the numbers at the top (950-9 in this case) being randomly chosen anew each time. Could an improvement be made to the program so that each new SMS message stays in the same conversation? ``` #include #include #include typedef struct { int lines_read; } UploadStatus; size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp) { if((size == 0) || (nmemb == 0) || ((size * nmemb) lines_read]; if(data) { size_t len = strlen(data); memcpy(ptr, data, len); upload->lines_read++; return len; } return 0; } int main(void) { CURLcode res = CURLE_OK; struct curl_slist *recipients = NULL; UploadStatus upload_ctx = {0}; const char *from = "test@gmail.com"; const char *to = "UrTxtEmail"; // see http://www.emailtextmessages.com/ CURL *curl = curl_easy_init(); if(curl) { // set username and password curl_easy_setopt(curl, CURLOPT_USERNAME, from); curl_easy_setopt(curl, CURLOPT_PASSWORD, "password"); curl_easy_setopt(curl, CURLOPT_URL, "smtp://
- pattern minor 112d agoTesting uptime of my personal serverI made some code to test my personal servers uptime. It logs in to my router page and sees if it returns status 200. A cron job runs it every 5 minutes. Please let me know if I can make the code more efficient. ``` ``` One thing I wanted to do was to somehow assign $OK to a variable and retrieve it the next time the page is loaded but I do not think PHP can do this so I saved it to an external file (OK.txt) and I read the value every time and increment it every time my site returns 200. Here is a sample output.txt file: `Server Uptime: 92.5% OK: 37, DOWN: 3 09/30 06:48:28 pm DOWN 09/30 06:48:28 pm DOWN 09/30 06:48:28 pm DOWN `
- pattern minor 112d agoPinging a URL with libcurlI've asked a question about pinging a URL before, but I wanted something that was a bit shorter and still just as efficient. libcurl seemed to be the perfect answer. Here is my method: ``` /** * @fn int testConnection(void) * @brief Pings "https://www.google.com/" to test if there is an internet connection. Timeout is set to three seconds. * @return Success value if connected to the internet. */ int testConnection(void) { CURL *curl; CURLcode res = 0; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com/"); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); res = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); return res; } ``` Is there anything "wrong" with this pinging method? Are there any ways that I could make this method more efficient?