Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Http Client API #309

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions api/include/opentelemetry/http/http_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright (c) Microsoft. All rights reserved
lalitb marked this conversation as resolved.
Show resolved Hide resolved

#pragma once

#include "opentelemetry/nostd/string_view.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace http
{


enum class HttpResult: uint8_t
{
// Response has been received successfully from target server.
HttpResult_OK = 0,

// Request has been aborted by the caller. The server might or
// might not have already received or processed the request.
HttpResult_Aborted = 1,

// Local conditions have prevented the request from being sent
// (invalid request parameters, out of memory, internal error etc.)
HttpResult_LocalFailure = 2,

// Network conditions somewhere between the local machine and
// the target server have caused the request to fail
// (connection failed, connection dropped abruptly etc.).
HttpResult_NetworkFailure = 3

};

// The HttpHeaders class contains a set of HTTP headers.
class HttpHeaders
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a place where do use HttpHeaders in API? Does it mean we need to have a transform somewhere from std::multimap<std::string, std::string> used within the SDK - to ABI-safe HttpHeaders implementation used in API surface? Can you provide some concrete example where we require this in API?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a use case for this in the API.

{
public:
// Inserts a name/value pair, and removes elements with the same name.
virtual void set(nostd::string_view const& name, nostd::string_view const& value) = 0;

// Inserts a name/value pair
virtual void add(nostd::string_view const& name, nostd::string_view const& value) = 0;

// Gets a string value given a name
virtual nostd::string_view const& get(nostd::string_view const& name) const = 0;
lalitb marked this conversation as resolved.
Show resolved Hide resolved

// Tests whether the headers contains the specified name.
lalitb marked this conversation as resolved.
Show resolved Hide resolved
virtual bool has(nostd::string_view const& name) const = 0;
};

// The HttpRequest class represents a Request object.
// Individual HTTP client implementations can implement the request object in
// the most efficient way. Either fill the request first, and then issue
// the underlying request, or create the real request immediately, and then forward
// the methods and set the individual parameters directly one by one.
class HttpRequest
{
public:
// Gets the request ID.
virtual const nostd::string_view& GetId() const = 0;

// Sets the request Method
virtual void SetMethod(nostd::string_view const& method) = 0;

// Gets the request URI
virtual void SetUrl(nostd::string_view const& url) = 0;

// Gets the request Headers
virtual HttpHeaders* GetHeaders() const = 0;

// Sets the request body
virtual void SetBody(const uint8_t* const body, const size_t len) = 0;

// Gets the request body
virtual void GetBody(uint8_t* body, size_t& len) = 0;
};

// The HttpResponse class represents a Response object.
// Individual HTTP client implementations can implement the response object
// in the most efficient way. Either copy all of the underlying data to a new
// structure, and provide it to the callback; or keep the real
// response data around, forward the methods, and retrieve the individual
// values directly one by one.
class HttpResponse
{
public:
// Gets the response ID.
virtual const nostd::string_view& GetId() = 0;

// Get the response result code.
virtual HttpResult GetResult() = 0;

// Gets the response status code.
virtual unsigned GetStatusCode() = 0;

// Gets the response headers.
virtual HttpHeaders* GetHeaders() = 0;

// Gets the response body.
virtual void GetBody(uint8_t* body, size_t& len) = 0;
};

// The HttpResponseCallback class receives HTTP client responses
class HttpResponseCallback
{
public:
// Called when an HTTP request completes.
// The passed response object contains details about the exact way the
// request finished (HTTP status code, headers, content, error codes
// etc.). The ownership of the response object is transferred to the
// callback object. It can store it for later if necessary. Finally, it
// must be deleted using its virtual destructor.
virtual void OnHttpResponse(HttpResponse* response) = 0;
};

// The HttpClient class is the interface for HTTP client implementations.
class HttpClient
{
public:

// Creates an empty HTTP request object.
// The created request object has only its ID prepopulated. Other fields
// must be set by the caller. The request object can then be sent
// using SendRequestAsync(). If you are not going to use the request object
// then you can delete it safely using its virtual destructor.
virtual HttpRequest* CreateRequest() = 0;

// Begins an HTTP request.
// The method takes ownership of the passed request, and can destroy it before
// returning to the caller. Do not access the request object in any
// way after this invocation, and do not delete it.
// The callback object is always called, even if the request is
// cancelled, or if an error occurs immediately during sending. In the
// latter case, the OnHttpResponse() callback is called before this
// method returns. You must keep the callback object alive until its
// OnHttpResponse() callback is called.
virtual void SendRequestAsync(HttpRequest* request, HttpResponseCallback* callback) = 0;

// Cancels an HTTP request.
// The caller must provide a string ID returned earlier by request->GetId().
// The request is cancelled asynchronously. The caller must still
// wait for the relevant OnHttpResponse() callback (it can just come
// earlier with some "aborted" error status).
virtual void CancelRequestAsync(nostd::string_view const& id) = 0;

virtual void CancelAllRequests()
{
}
};

} // namespace nostd
OPENTELEMETRY_END_NAMESPACE
156 changes: 156 additions & 0 deletions sdk/include/opentelemetry/sdk/http/http_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright (c) Microsoft. All rights reserved.

#pragma once
#include "opentelemetry/http/http_client.h"
#include "opentelemetry/version.h"

#include <map>
#include <vector>

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace http
{
namespace http_api = opentelemetry::http;

// HttpHeaders implementation
class HttpHeaders: http_api::HttpHeaders, std::multimap<std::string, std::string>
{

public:
virtual void set(nostd::string_view const& name, nostd::string_view const& value) override
{
auto range = equal_range(std::string(name.data()));
auto hint = erase(range.first, range.second);
insert(hint, std::make_pair(name, value));
}

virtual void add(nostd::string_view const& name, nostd::string_view const& value) override
{
insert(std::make_pair(name, value));
}

virtual nostd::string_view const& get(nostd::string_view const& name) const override
{
auto it = find(std::string(name.data()));
return (it != end()) ? it->second : m_empty;
}

virtual bool has(nostd::string_view const& name) const override
{
auto it = find(std::string(name.data()));
return (it != end());
}

private:
nostd::string_view m_empty{};
};

class SimpleHttpRequest: public http_api::HttpRequest
{

public:

SimpleHttpRequest(nostd::string_view const& id): id_(id), method_("GET")
{
}

// Gets the HTTP request ID.
virtual const nostd::string_view& GetId() const override
{
return id_;
}

// Sets the request method
virtual void SetMethod(nostd::string_view const& method) override
{
method_ = method;
}

// Sets the HTTP request URI.
virtual void SetUrl(nostd::string_view const& url) override
{
url_ = url;
}

// Gets the HTTP request headers.
virtual http_api::HttpHeaders* GetHeaders() const override
{
return headers_;
}

// Sets the request body.
virtual void SetBody(const uint8_t* const body, const size_t len) override
{
for (int i = 0; i < len; i++)
{
body_.push_back(body[i]);
}
}

virtual void GetBody(uint8_t* body, size_t& len) override
{
len = 0;
for (auto &e: body_)
{
body[len++] = e;
}
len = (len > 0 ) ? len - 1 : len ;
}

private:
http_api::HttpHeaders* headers_;
std::vector<uint8_t> body_;
nostd::string_view method_;
nostd::string_view id_;
nostd::string_view url_;


};

class SimpleHttpResponse: public http_api::HttpResponse
{

public:
SimpleHttpResponse(nostd::string_view const& id):
id_(id),
result_(http_api::HttpResult::HttpResult_LocalFailure),
statusCode_(0)
{
}

virtual http_api::HttpResult GetResult() override
{
return result_;
}

virtual unsigned GetStatusCode() override
{
return statusCode_;
}

virtual http_api::HttpHeaders* GetHeaders() override
{
return headers_;
}

virtual void GetBody(uint8_t* body, size_t& len) override
{
int i = 0;
for (auto &e: body_)
{
body_[i++] = e;
}
}

private:
nostd::string_view id_;
unsigned statusCode_;
http_api::HttpHeaders* headers_;
http_api::HttpResult result_;
std::vector<uint8_t> body_;
};
} //http
} //sdk
OPENTELEMETRY_END_NAMESPACE