Unverified Commit 2db95183 authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

Merge pull request #312 from hasankandemir1993/master

Ghost cookie problem, hashmap of hashmaps solution
parents bf80caf9 1982407f
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <string> #include <string>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include <list>
#include <pistache/optional.h> #include <pistache/optional.h>
#include <pistache/http_defs.h> #include <pistache/http_defs.h>
...@@ -41,50 +43,75 @@ struct Cookie { ...@@ -41,50 +43,75 @@ struct Cookie {
class CookieJar { class CookieJar {
public: public:
using Storage = std::unordered_map<std::string, Cookie>; using HashMapCookies = std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> { struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> {
iterator(const Storage::const_iterator& _iterator) iterator(const Storage::const_iterator& _iterator)
: it_(_iterator) : iter_storage(_iterator)
{ } {
}
iterator(const Storage::const_iterator& _iterator, const Storage::const_iterator& end)
: iter_storage(_iterator),iter_storage_end(end)
{
if(iter_storage != iter_storage_end) {
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const { Cookie operator*() const {
return it_->second; return iter_cookie_values->second; // return iter_storage->second;
} }
iterator operator++() { iterator operator++() {
++it_; ++iter_cookie_values;
return iterator(it_); if(iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if(iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return iterator(iter_storage,iter_storage_end);
} }
iterator operator++(int) { iterator operator++(int) {
iterator ret(it_); iterator ret(iter_storage,iter_storage_end);
++it_; ++iter_cookie_values;
if(iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if(iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
return ret; return ret;
} }
bool operator !=(iterator other) const { bool operator !=(iterator other) const {
return it_ != other.it_; return iter_storage != other.iter_storage;
} }
bool operator==(iterator other) const { bool operator==(iterator other) const {
return it_ == other.it_; return iter_storage == other.iter_storage;
} }
private: private:
Storage::const_iterator it_; Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator iter_storage_end; // we need to know where main hashmap ends.
}; };
CookieJar(); CookieJar();
void add(const Cookie& cookie); void add(const Cookie& cookie);
void removeCookie(const std::string& name); // Unimplemented
void addFromRaw(const char *str, size_t len); void addFromRaw(const char *str, size_t len);
Cookie get(const std::string& name) const; Cookie get(const std::string& name) const;
bool has(const std::string& name) const; bool has(const std::string& name) const;
iterator begin() const { iterator begin() const {
return iterator(cookies.begin()); return iterator(cookies.begin(), cookies.end());
} }
iterator end() const { iterator end() const {
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <pistache/cookie.h> #include <pistache/cookie.h>
#include <pistache/stream.h> #include <pistache/stream.h>
using namespace std;
namespace Pistache { namespace Pistache {
namespace Http { namespace Http {
...@@ -207,7 +209,24 @@ CookieJar::CookieJar() ...@@ -207,7 +209,24 @@ CookieJar::CookieJar()
void void
CookieJar::add(const Cookie& cookie) { CookieJar::add(const Cookie& cookie) {
cookies.insert(std::make_pair(cookie.name, cookie));
std::string cookieName = cookie.name;
std::string cookieValue = cookie.value;
Storage::iterator it = cookies.find(cookieName);
if(it == cookies.end()) {
HashMapCookies hashmapWithFirstCookie;
hashmapWithFirstCookie.insert(std::make_pair(cookieValue,cookie));
cookies.insert(std::make_pair(cookieName, hashmapWithFirstCookie));
} else {
it->second.insert(std::make_pair(cookieValue,cookie));
}
}
void // Unimplemented
CookieJar::removeCookie(const std::string& name) {
// Empty for now, can be used later
} }
void void
...@@ -241,17 +260,16 @@ CookieJar::addFromRaw(const char *str, size_t len) { ...@@ -241,17 +260,16 @@ CookieJar::addFromRaw(const char *str, size_t len) {
Cookie Cookie
CookieJar::get(const std::string& name) const { CookieJar::get(const std::string& name) const {
auto it = cookies.find(name); Storage::const_iterator it = cookies.find(name);
if (it == std::end(cookies)) if(it != cookies.end()) {
return it->second.begin()->second; // it returns begin(), first element, could be changed.
}
throw std::runtime_error("Could not find requested cookie"); throw std::runtime_error("Could not find requested cookie");
return it->second;
} }
bool bool
CookieJar::has(const std::string& name) const { CookieJar::has(const std::string& name) const {
auto it = cookies.find(name); return cookies.find(name) != cookies.end();
return it != std::end(cookies);
} }
} // namespace Http } // namespace Http
......
...@@ -14,6 +14,7 @@ pistache_test(async_test) ...@@ -14,6 +14,7 @@ pistache_test(async_test)
pistache_test(typeid_test) pistache_test(typeid_test)
pistache_test(router_test) pistache_test(router_test)
pistache_test(cookie_test) pistache_test(cookie_test)
pistache_test(cookie_test_2)
pistache_test(view_test) pistache_test(view_test)
pistache_test(http_parsing_test) pistache_test(http_parsing_test)
pistache_test(http_uri_test) pistache_test(http_uri_test)
......
#include "gtest/gtest.h"
#include <pistache/cookie.h>
#include <pistache/date.h>
using namespace Pistache;
using namespace Pistache::Http;
void addCookies(const char* str, std::function<void (const CookieJar&)> testFunc) {
CookieJar jar;
jar.addFromRaw(str, strlen(str));
testFunc(jar);
}
TEST(cookie_test_2, cookiejar_test_2) {
addCookies("key=value1; key=value2; key2=; key2=foo=bar", [](const CookieJar& jar) {
int count = 0;
for (const auto& c: jar) {
count++;
}
ASSERT_EQ(count,4); // number of cookies must be 4 in this case
});
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment