OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::GUI::HttpServer Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/HttpServer.hpp>

Collaboration diagram for Slic3r::GUI::HttpServer:

Classes

class  Response
class  ResponseNotFound
class  ResponseRedirect
class  ResponseHtml
class  IOServer

Public Member Functions

 HttpServer (boost::asio::ip::port_type port=LOCALHOST_PORT)
 ~HttpServer ()
bool is_started ()
void start ()
void stop ()
void set_port (boost::asio::ip::port_type new_port)
boost::asio::ip::port_type get_port () const
void set_request_handler (const std::function< std::shared_ptr< Response >(const std::string &)> &m_request_handler)

Static Public Member Functions

static std::shared_ptr< Response > bbl_auth_handle_request (const std::string &url)
static std::shared_ptr< Response > auth_handle_request (const std::string &url, const std::string &provider)

Public Attributes

boost::thread m_http_server_thread
bool start_http_server = false

Private Attributes

boost::asio::ip::port_type port
std::unique_ptr< IOServer > server_ {nullptr}
std::function< std::shared_ptr< Response >(const std::string &)> m_request_handler {&HttpServer::bbl_auth_handle_request}

Friends

class session

Detailed Description

Constructor & Destructor Documentation

◆ HttpServer()

Slic3r::GUI::HttpServer::HttpServer ( boost::asio::ip::port_type port = LOCALHOST_PORT)
171: port(port) {}
boost::asio::ip::port_type port
Definition HttpServer.hpp:82

References port.

Referenced by Slic3r::GUI::HttpServer::IOServer::IOServer().

Here is the caller graph for this function:

◆ ~HttpServer()

Slic3r::GUI::HttpServer::~HttpServer ( )
174{
175 stop();
176}
void stop()
Definition HttpServer.cpp:197

References stop().

Here is the call graph for this function:

Member Function Documentation

◆ auth_handle_request()

std::shared_ptr< HttpServer::Response > Slic3r::GUI::HttpServer::auth_handle_request ( const std::string & url,
const std::string & provider )
static
226{
227 BOOST_LOG_TRIVIAL(info) << "thirdparty_login: get_response";
228
229 const std::string auth_code = url_get_param(url, "code");
230 if (!auth_code.empty()) {
231 std::string state = url_get_param(url, "orca_state");
232 if (state.empty()) {
233 state = url_get_param(url, "state"); // fallback
234 }
235 NetworkAgent* agent = wxGetApp().getAgent();
236 if (!agent) {
237 return std::make_shared<ResponseNotFound>();
238 }
239
240 json payload;
241 payload["command"] = "user_login";
242 payload["data"]["code"] = auth_code;
243 payload["data"]["state"] = state;
244
245 agent->change_user(payload.dump(), provider);
246 const bool login_ok = agent->is_user_login(provider);
247 if (login_ok) {
248 wxGetApp().request_user_login(1, provider);
249 GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); });
250 }
251
252 const std::string title = login_ok ? _u8L("Authentication complete") : _u8L("Authentication failed");
253 const std::string message = login_ok
254 ? _u8L("You can return to OrcaSlicer. This window will close automatically.")
255 : _u8L("Something went wrong. Please return to OrcaSlicer and try again.");
256 const std::string html =
257 "<html><head><meta charset=\"utf-8\">"
258 "<style>body{font-family:Arial,sans-serif;background:#f7f7f7;color:#222;margin:32px;}"
259 "a.button{display:inline-block;padding:10px 16px;margin-top:12px;background:#0f8bff;color:#fff;text-decoration:none;border-radius:6px;}"
260 "</style></head><body><div class=\"container\">"
261 "<h2>" + title + "</h2>"
262 "<p>" + message + "</p>"
263 "<script>setTimeout(function(){try{window.close();}catch(e){}},1500);</script>"
264 "</div></body></html>";
265 return std::make_shared<ResponseHtml>(html);
266 }
267
268 if (boost::contains(url, "access_token")) {
269 std::string redirect_url = url_get_param(url, "redirect_url");
270 std::string access_token = url_get_param(url, "access_token");
271 std::string refresh_token = url_get_param(url, "refresh_token");
272 std::string expires_in_str = url_get_param(url, "expires_in");
273 std::string refresh_expires_in_str = url_get_param(url, "refresh_expires_in");
274 NetworkAgent* agent = wxGetApp().getAgent();
275
276 unsigned int http_code;
277 std::string http_body;
278 int result = agent->get_my_profile(access_token, &http_code, &http_body, provider);
279 if (result == 0) {
280 std::string user_id;
281 std::string user_name;
282 std::string user_account;
283 std::string user_avatar;
284 try {
285 json user_j = json::parse(http_body);
286 if (user_j.contains("uidStr"))
287 user_id = user_j["uidStr"].get<std::string>();
288 if (user_j.contains("name"))
289 user_name = user_j["name"].get<std::string>();
290 if (user_j.contains("avatar"))
291 user_avatar = user_j["avatar"].get<std::string>();
292 if (user_j.contains("account"))
293 user_account = user_j["account"].get<std::string>();
294 } catch (...) {
295 ;
296 }
297 json j;
298 j["data"]["refresh_token"] = refresh_token;
299 j["data"]["token"] = access_token;
300 j["data"]["expires_in"] = expires_in_str;
301 j["data"]["refresh_expires_in"] = refresh_expires_in_str;
302 j["data"]["user"]["uid"] = user_id;
303 j["data"]["user"]["name"] = user_name;
304 j["data"]["user"]["account"] = user_account;
305 j["data"]["user"]["avatar"] = user_avatar;
306 agent->change_user(j.dump(), provider);
307 if (agent->is_user_login(provider)) {
308 wxGetApp().request_user_login(1, provider);
309 }
310 GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); });
311 std::string location_str = (boost::format("%1%?result=success") % redirect_url).str();
312 return std::make_shared<ResponseRedirect>(location_str);
313 } else {
314 std::string error_str = "get_user_profile_error_" + std::to_string(result);
315 std::string location_str = (boost::format("%1%?result=fail&error=%2%") % redirect_url % error_str).str();
316 return std::make_shared<ResponseRedirect>(location_str);
317 }
318 }
319
320 // Ticket-based redirect: Bambu Lab's auth server redirects here after a
321 // third-party (Google) OAuth so that the access token never travels through
322 // the URL. We exchange the ticket via the network plugin's get_my_token,
323 // then run the same get_my_profile + change_user flow as access_token.
324 // Skip entirely on legacy plugins missing bambu_network_get_my_token —
325 // those clients pin X-BBL-Client-Version so the server stays on the legacy
326 // ?access_token= redirect path and never sends ?ticket= here.
327 const std::string ticket = url_get_param(url, "ticket");
328 const std::string ticket_redirect_url = url_get_param(url, "redirect_url");
329 if (!ticket.empty() && !ticket_redirect_url.empty() &&
331 BOOST_LOG_TRIVIAL(info) << "thirdparty_login: ticket flow";
332 NetworkAgent* agent = wxGetApp().getAgent();
333 if (!agent) {
334 std::string location_str = (boost::format("%1%?result=fail&error=no_agent") % ticket_redirect_url).str();
335 return std::make_shared<ResponseRedirect>(location_str);
336 }
337
338 auto fail_redirect = [&ticket_redirect_url](const std::string& reason) {
339 std::string location_str = (boost::format("%1%?result=fail&error=%2%") % ticket_redirect_url % reason).str();
340 return std::make_shared<ResponseRedirect>(location_str);
341 };
342
343 unsigned int token_http_code = 0;
344 std::string token_body;
345 int token_result = agent->get_my_token(ticket, &token_http_code, &token_body, provider);
346 if (token_result != 0) {
347 BOOST_LOG_TRIVIAL(warning) << "thirdparty_login: get_my_token failed, http_code=" << token_http_code;
348 return fail_redirect("get_my_token_error_" + std::to_string(token_result));
349 }
350
351 std::string access_token;
352 std::string refresh_token;
353 std::string expires_in_str;
354 std::string refresh_expires_in_str;
355 try {
356 json token_j = json::parse(token_body);
357 if (token_j.contains("accessToken"))
358 access_token = token_j["accessToken"].get<std::string>();
359 if (token_j.contains("refreshToken"))
360 refresh_token = token_j["refreshToken"].get<std::string>();
361 if (token_j.contains("expiresIn"))
362 expires_in_str = std::to_string(token_j["expiresIn"].get<double>());
363 if (token_j.contains("refreshExpiresIn"))
364 refresh_expires_in_str = std::to_string(token_j["refreshExpiresIn"].get<double>());
365 } catch (...) {
366 return fail_redirect("token_parse_error");
367 }
368
369 if (access_token.empty()) {
370 return fail_redirect("token_missing");
371 }
372
373 unsigned int profile_http_code = 0;
374 std::string profile_body;
375 int profile_result = agent->get_my_profile(access_token, &profile_http_code, &profile_body, provider);
376 if (profile_result != 0) {
377 BOOST_LOG_TRIVIAL(warning) << "thirdparty_login: get_my_profile failed, http_code=" << profile_http_code;
378 return fail_redirect("get_user_profile_error_" + std::to_string(profile_result));
379 }
380
381 std::string user_id;
382 std::string user_name;
383 std::string user_account;
384 std::string user_avatar;
385 try {
386 json user_j = json::parse(profile_body);
387 if (user_j.contains("uidStr"))
388 user_id = user_j["uidStr"].get<std::string>();
389 if (user_j.contains("name"))
390 user_name = user_j["name"].get<std::string>();
391 if (user_j.contains("avatar"))
392 user_avatar = user_j["avatar"].get<std::string>();
393 if (user_j.contains("account"))
394 user_account = user_j["account"].get<std::string>();
395 } catch (...) {
396 BOOST_LOG_TRIVIAL(warning) << "thirdparty_login: profile JSON parse failed";
397 }
398
399 json j;
400 j["data"]["refresh_token"] = refresh_token;
401 j["data"]["token"] = access_token;
402 j["data"]["expires_in"] = expires_in_str;
403 j["data"]["refresh_expires_in"] = refresh_expires_in_str;
404 j["data"]["user"]["uid"] = user_id;
405 j["data"]["user"]["name"] = user_name;
406 j["data"]["user"]["account"] = user_account;
407 j["data"]["user"]["avatar"] = user_avatar;
408 agent->change_user(j.dump(), provider);
409 if (agent->is_user_login(provider)) {
410 wxGetApp().request_user_login(1, provider);
411 }
412 GUI::wxGetApp().CallAfter([] { wxGetApp().ShowUserLogin(false); });
413 std::string location_str = (boost::format("%1%?result=success") % ticket_redirect_url).str();
414 return std::make_shared<ResponseRedirect>(location_str);
415 }
416
417 return std::make_shared<ResponseNotFound>();
418}
static BBLNetworkPlugin & instance()
Definition BBLNetworkPlugin.cpp:56
func_get_my_token get_get_my_token() const
Definition BBLNetworkPlugin.hpp:395
std::string url_get_param(const std::string &url, const std::string &key)
Definition HttpServer.cpp:35
nlohmann::json json
Definition AssembleList.cpp:42
#define _u8L(s)
Definition I18N.hpp:11

References _u8L, Slic3r::NetworkAgent::change_user(), Slic3r::NetworkAgent::get_my_profile(), Slic3r::NetworkAgent::get_my_token(), Slic3r::BBLNetworkPlugin::instance(), Slic3r::NetworkAgent::is_user_login(), and Slic3r::GUI::url_get_param().

Referenced by bbl_auth_handle_request(), Slic3r::GUI::GUI_App::start_http_server(), and Slic3r::GUI::GUI_App::start_http_server().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ bbl_auth_handle_request()

std::shared_ptr< HttpServer::Response > Slic3r::GUI::HttpServer::bbl_auth_handle_request ( const std::string & url)
static
221{
223}
static std::shared_ptr< Response > auth_handle_request(const std::string &url, const std::string &provider)
Definition HttpServer.cpp:225
static const std::string BBL_CLOUD_PROVIDER("bbl")

References auth_handle_request(), and Slic3r::BBL_CLOUD_PROVIDER().

Here is the call graph for this function:

◆ get_port()

boost::asio::ip::port_type Slic3r::GUI::HttpServer::get_port ( ) const
inline
129{ return port; }

References port.

◆ is_started()

bool Slic3r::GUI::HttpServer::is_started ( )
inline
125{ return start_http_server; }
bool start_http_server
Definition HttpServer.hpp:123

References start_http_server.

◆ set_port()

void Slic3r::GUI::HttpServer::set_port ( boost::asio::ip::port_type new_port)
inline
128{ port = new_port; }

References port.

◆ set_request_handler()

void Slic3r::GUI::HttpServer::set_request_handler ( const std::function< std::shared_ptr< Response >(const std::string &)> & m_request_handler)
216{
217 this->m_request_handler = request_handler;
218}
std::function< std::shared_ptr< Response >(const std::string &)> m_request_handler
Definition HttpServer.hpp:156

References m_request_handler.

◆ start()

void Slic3r::GUI::HttpServer::start ( )
179{
181 return;
182
183 BOOST_LOG_TRIVIAL(info) << "start_http_service...";
184 server_ = std::make_unique<IOServer>(*this);
185 IOServer* io_server = server_.get();
186 start_http_server = true;
187 m_http_server_thread = create_thread([io_server] {
188 set_current_thread_name("http_server");
189 io_server->acceptor.listen();
190
191 io_server->do_accept();
192
193 io_server->io_service.run();
194 });
195}
Definition HttpServer.hpp:137
std::unique_ptr< IOServer > server_
Definition HttpServer.hpp:154
boost::thread m_http_server_thread
Definition HttpServer.hpp:122
boost::thread create_thread(boost::thread::attributes &attrs, Fn &&fn)
Definition Thread.hpp:48
bool set_current_thread_name(const char *thread_name)
Definition Thread.cpp:187

References Slic3r::GUI::HttpServer::IOServer::acceptor, Slic3r::create_thread(), Slic3r::GUI::HttpServer::IOServer::do_accept(), Slic3r::GUI::HttpServer::IOServer::io_service, m_http_server_thread, server_, Slic3r::set_current_thread_name(), and start_http_server.

Referenced by Slic3r::GUI::HttpServer::IOServer::do_accept().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stop()

void Slic3r::GUI::HttpServer::stop ( )
198{
199 start_http_server = false;
200 if (server_) {
201 IOServer* io_server = server_.get();
202 boost::asio::post(io_server->io_service, [io_server] {
203 boost::system::error_code ec;
204 io_server->acceptor.cancel(ec);
205 io_server->acceptor.close(ec);
206 io_server->stop_all();
207 io_server->io_service.stop();
208 });
209 }
210 if (m_http_server_thread.joinable())
212 server_.reset();
213}

References Slic3r::GUI::HttpServer::IOServer::io_service, m_http_server_thread, server_, and start_http_server.

Referenced by ~HttpServer().

Here is the caller graph for this function:

◆ session

friend class session
friend

Member Data Documentation

◆ m_http_server_thread

boost::thread Slic3r::GUI::HttpServer::m_http_server_thread

Referenced by start(), and stop().

◆ m_request_handler

std::function<std::shared_ptr<Response>(const std::string&)> Slic3r::GUI::HttpServer::m_request_handler {&HttpServer::bbl_auth_handle_request}
private
static std::shared_ptr< Response > bbl_auth_handle_request(const std::string &url)
Definition HttpServer.cpp:220

Referenced by set_request_handler().

◆ port

boost::asio::ip::port_type Slic3r::GUI::HttpServer::port
private

Referenced by HttpServer(), get_port(), and set_port().

◆ server_

std::unique_ptr<IOServer> Slic3r::GUI::HttpServer::server_ {nullptr}
private
154{nullptr};

Referenced by start(), and stop().

◆ start_http_server

bool Slic3r::GUI::HttpServer::start_http_server = false

Referenced by is_started(), start(), and stop().


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/HttpServer.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/slic3r/GUI/HttpServer.cpp