Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit 0095ad2

Browse files
committed
Merge pull request #5 from googlesamples/master
Merge my fork up to head.
2 parents ad17ca1 + 424e1bf commit 0095ad2

File tree

7 files changed

+5668
-126
lines changed

7 files changed

+5668
-126
lines changed

Firebase.cpp

Lines changed: 130 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -15,109 +15,169 @@
1515
//
1616
#include "Firebase.h"
1717

18-
const char* firebaseFingerprint = "7A 54 06 9B DC 7A 25 B3 86 8D 66 53 48 2C 0B 96 42 C7 B3 0A";
19-
const uint16_t firebasePort = 443;
18+
// Detect whether stable version of HTTP library is installed instead of
19+
// master branch and patch in missing status and methods.
20+
#ifndef HTTP_CODE_TEMPORARY_REDIRECT
21+
#define HTTP_CODE_TEMPORARY_REDIRECT 307
22+
#define USE_ESP_ARDUINO_CORE_2_0_0
23+
#endif
2024

21-
Firebase::Firebase(const String& host) : _host(host) {
22-
_http.setReuse(true);
25+
namespace {
26+
const char* kFirebaseFingerprint = "7A 54 06 9B DC 7A 25 B3 86 8D 66 53 48 2C 0B 96 42 C7 B3 0A";
27+
const uint16_t kFirebasePort = 443;
28+
29+
String makeFirebaseURL(const String& path, const String& auth) {
30+
String url;
31+
if (path[0] != '/') {
32+
url = "/";
33+
}
34+
url += path + ".json";
35+
if (auth.length() > 0) {
36+
url += "?auth=" + auth;
37+
}
38+
return url;
39+
}
40+
41+
} // namespace
42+
43+
Firebase::Firebase(const String& host) : host_(host) {
44+
http_.setReuse(true);
2345
}
2446

2547
Firebase& Firebase::auth(const String& auth) {
26-
_auth = auth;
48+
auth_ = auth;
2749
return *this;
2850
}
2951

30-
String Firebase::get(const String& path) {
31-
sendRequest("GET", path);
32-
return readBody();
52+
FirebaseGet Firebase::get(const String& path) {
53+
return FirebaseGet(host_, auth_, path, &http_);
54+
}
55+
56+
FirebaseSet Firebase::set(const String& path, const String& value) {
57+
return FirebaseSet(host_, auth_, path, value, &http_);
3358
}
3459

35-
String Firebase::push(const String& path, const String& value) {
36-
sendRequest("POST", path, value);
37-
return readBody();
60+
FirebasePush Firebase::push(const String& path, const String& value) {
61+
return FirebasePush(host_, auth_, path, value, &http_);
3862
}
3963

40-
void Firebase::remove(const String& path) {
41-
sendRequest("DELETE", path);
64+
FirebaseRemove Firebase::remove(const String& path) {
65+
return FirebaseRemove(host_, auth_, path, &http_);
4266
}
4367

44-
Firebase& Firebase::stream(const String& path) {
45-
_error.reset();
46-
String url = makeURL(path);
47-
const char* headers[] = {"Location"};
48-
_http.setReuse(true);
49-
_http.begin(_host.c_str(), firebasePort, url.c_str(), true, firebaseFingerprint);
50-
_http.collectHeaders(headers, 1);
51-
_http.addHeader("Accept", "text/event-stream");
52-
int statusCode = _http.sendRequest("GET", (uint8_t*)NULL, 0);
53-
String location;
54-
// TODO(proppy): Add a max redirect check
55-
while (statusCode == 307) {
56-
location = _http.header("Location");
57-
_http.setReuse(false);
58-
_http.end();
59-
_http.setReuse(true);
60-
_http.begin(location, firebaseFingerprint);
61-
statusCode = _http.sendRequest("GET", (uint8_t*)NULL, 0);
68+
FirebaseStream Firebase::stream(const String& path) {
69+
// TODO: create new client dedicated to stream.
70+
return FirebaseStream(host_, auth_, path, &http_);
71+
}
72+
73+
// FirebaseCall
74+
FirebaseCall::FirebaseCall(const String& host, const String& auth,
75+
const char* method, const String& path,
76+
const String& data, HTTPClient* http) : http_(http) {
77+
String url = makeFirebaseURL(path, auth);
78+
http_->setReuse(true);
79+
http_->begin(host, kFirebasePort, url, true, kFirebaseFingerprint);
80+
81+
bool followRedirect = false;
82+
if (method == "STREAM") {
83+
method = "GET";
84+
http_->addHeader("Accept", "text/event-stream");
85+
followRedirect = true;
6286
}
63-
if (statusCode != 200) {
64-
_error.set(statusCode,
65-
"stream " + location + ": "
66-
+ HTTPClient::errorToString(statusCode));
87+
88+
if (followRedirect) {
89+
const char* headers[] = {"Location"};
90+
http_->collectHeaders(headers, 1);
6791
}
68-
return *this;
69-
}
7092

71-
String Firebase::makeURL(const String& path) {
72-
String url;
73-
if (path[0] != '/') {
74-
url = "/";
93+
int status = http_->sendRequest(method, (uint8_t*)data.c_str(), data.length());
94+
95+
// TODO: Add a max redirect check
96+
if (followRedirect) {
97+
while (status == HTTP_CODE_TEMPORARY_REDIRECT) {
98+
String location = http_->header("Location");
99+
http_->setReuse(false);
100+
http_->end();
101+
http_->setReuse(true);
102+
http_->begin(location, kFirebaseFingerprint);
103+
status = http_->sendRequest("GET", (uint8_t*)NULL, 0);
104+
}
75105
}
76-
url += path + ".json";
77-
if (_auth.length() > 0) {
78-
url += "?auth=" + _auth;
106+
107+
if (status != 200) {
108+
#ifdef USE_ESP_ARDUINO_CORE_2_0_0
109+
error_ = FirebaseError(status, String(method) + " " + url + ": " + status);
110+
#else
111+
error_ = FirebaseError(status, String(method) + " " + url + ": " + HTTPClient::errorToString(status));
112+
#endif
113+
}
114+
115+
// if not streaming.
116+
if (!followRedirect) {
117+
response_ = http_->getString();
79118
}
80-
return url;
81119
}
82120

83-
void Firebase::sendRequest(const char* method, const String& path, const String& value) {
84-
String url = makeURL(path);
85-
_http.begin(_host.c_str(), firebasePort, url.c_str(), true, firebaseFingerprint);
86-
int statusCode = _http.sendRequest(method, (uint8_t*)value.c_str(), value.length());
87-
_error.reset();
88-
if (statusCode < 0) {
89-
_error.set(statusCode,
90-
String(method) + " " + url + ": "
91-
+ HTTPClient::errorToString(statusCode));
92-
}
121+
// FirebaseGet
122+
FirebaseGet::FirebaseGet(const String& host, const String& auth,
123+
const String& path,
124+
HTTPClient* http)
125+
: FirebaseCall(host, auth, "GET", path, "", http) {
126+
if (!error()) {
127+
// TODO: parse json
128+
json_ = response();
129+
}
93130
}
94131

95-
String Firebase::readBody() {
96-
if (_error.code() != 0) {
97-
return "";
132+
// FirebaseSet
133+
FirebaseSet::FirebaseSet(const String& host, const String& auth,
134+
const String& path, const String& value,
135+
HTTPClient* http)
136+
: FirebaseCall(host, auth, "PUT", path, value, http) {
137+
if (!error()) {
138+
// TODO: parse json
139+
json_ = response();
98140
}
99-
// no _http.end() because of connection reuse.
100-
return _http.getString();
141+
}
142+
// FirebasePush
143+
FirebasePush::FirebasePush(const String& host, const String& auth,
144+
const String& path, const String& value,
145+
HTTPClient* http)
146+
: FirebaseCall(host, auth, "POST", path, value, http) {
147+
if (!error()) {
148+
// TODO: parse name
149+
name_ = response();
150+
}
151+
}
152+
153+
// FirebasePush
154+
FirebaseRemove::FirebaseRemove(const String& host, const String& auth,
155+
const String& path,
156+
HTTPClient* http)
157+
: FirebaseCall(host, auth, "DELETE", path, "", http) {
101158
}
102159

103-
bool Firebase::connected() {
104-
return _http.connected();
160+
// FirebaseStream
161+
FirebaseStream::FirebaseStream(const String& host, const String& auth,
162+
const String& path,
163+
HTTPClient* http)
164+
: FirebaseCall(host, auth, "STREAM", path, "", http) {
105165
}
106166

107-
bool Firebase::available() {
108-
return _http.getStreamPtr()->available();
167+
bool FirebaseStream::available() {
168+
return http_->getStreamPtr()->available();
109169
}
110170

111-
Firebase::Event Firebase::read(String& event) {
112-
auto client = _http.getStreamPtr();
113-
Event type;;
171+
FirebaseStream::Event FirebaseStream::read(String& event) {
172+
auto client = http_->getStreamPtr();
173+
Event type;
114174
String typeStr = client->readStringUntil('\n').substring(7);
115175
if (typeStr == "put") {
116-
type = Firebase::Event::PUT;
176+
type = Event::PUT;
117177
} else if (typeStr == "patch") {
118-
type = Firebase::Event::PATCH;
178+
type = Event::PATCH;
119179
} else {
120-
type = Firebase::Event::UNKNOWN;
180+
type = Event::UNKNOWN;
121181
}
122182
event = client->readStringUntil('\n').substring(6);
123183
client->readStringUntil('\n'); // consume separator

0 commit comments

Comments
 (0)