Skip to content

Commit

Permalink
Simplify exception headers code
Browse files Browse the repository at this point in the history
Summary:
Now that we can set response headers directly from Haskell-land, let's simplify this code. This also serves the purpose of testing the new headers code

Future work:
- set exception meta headers for exception qualifiers (safe, stateful, permanent, etc.)
- user api for setting custom response headers

Reviewed By: simonmar

Differential Revision: D49908262

fbshipit-source-id: 72d6cc678ea6183e0b12fe65d73d7b247d343b9d
  • Loading branch information
Pepe Iborra authored and facebook-github-bot committed Oct 16, 2023
1 parent e8db373 commit 718c604
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 51 deletions.
53 changes: 22 additions & 31 deletions server/Thrift/Server/ProcessorCallback.hsc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ deleteProcessorCallback = freeHaskellFunPtr

data TResponse

kEx, kUex, kUexw, kAppClientErrorCode, kAppServerErrorCode :: ByteString
kEx = UTF8.fromString "ex"
kUex = UTF8.fromString "uex"
kUexw = UTF8.fromString "uexw"
kAppClientErrorCode = "23"
kAppServerErrorCode = "24"

-- | A function that will be called from C back into Haskell
-- Takes protocol id, input data, input length, pointer to fill with output
-- length, and returns a newly malloc'd set of bytes
Expand All @@ -71,36 +78,14 @@ handlerWrapper counter handler postProcess prot_id input_str input_len response_
#{poke apache::thrift::TResponse, data} response_ptr output_str
#{poke apache::thrift::TResponse, len} response_ptr
(fromIntegral output_len :: CSize)
case exc of
Just (SomeException ex, blame) -> do
(ex_name, ex_name_len) <- newByteStringAsCStringLen
$ UTF8.fromString
$ show
$ typeOf ex
(ex_text, ex_text_len) <- newByteStringAsCStringLen
$ UTF8.fromString
$ take 1024
$ show ex
#{poke apache::thrift::TResponse, ex_name} response_ptr ex_name
#{poke apache::thrift::TResponse, ex_name_len} response_ptr
(fromIntegral ex_name_len :: CSize)
#{poke apache::thrift::TResponse, ex_text} response_ptr ex_text
#{poke apache::thrift::TResponse, ex_text_len} response_ptr
(fromIntegral ex_text_len :: CSize)
#{poke apache::thrift::TResponse, client_error} response_ptr
(blame == ClientError)
Nothing -> do
#{poke apache::thrift::TResponse, ex_name} response_ptr nullPtr
#{poke apache::thrift::TResponse, ex_name_len} response_ptr (0 :: CSize)
#{poke apache::thrift::TResponse, ex_text} response_ptr nullPtr
#{poke apache::thrift::TResponse, ex_text_len} response_ptr (0 :: CSize)

for_ headers $ \(n,v) ->
BS.unsafeUseAsCStringLen n $ \(n_str, n_len) ->
BS.unsafeUseAsCStringLen v $ \(v_str, v_len) ->
addHeaderToResponse
response_ptr n_str (fromIntegral n_len) v_str (fromIntegral v_len)

for_ exc $ \(SomeException ex, blame) -> do
addHeaderToResponse kUex (UTF8.fromString $ show $ typeOf ex)
addHeaderToResponse kUexw (UTF8.fromString $ take 1024 $ show ex)
addHeaderToResponse kEx $
if blame == ClientError
then kAppClientErrorCode
else kAppServerErrorCode
for_ headers $ uncurry addHeaderToResponse
where
-- Allocates a new buffer to give away ownership of memory
newByteStringAsCStringLen :: ByteString -> IO CStringLen
Expand All @@ -110,9 +95,15 @@ handlerWrapper counter handler postProcess prot_id input_str input_len response_
copyBytes buf src len
return (buf, len)

addHeaderToResponse n v =
BS.unsafeUseAsCStringLen n $ \(n_str, n_len) ->
BS.unsafeUseAsCStringLen v $ \(v_str, v_len) ->
addHeaderToResponse_c
response_ptr n_str (fromIntegral n_len) v_str (fromIntegral v_len)

foreign import ccall "wrapper"
mkProcessorCallback :: ProcessorCallback -> IO (FunPtr ProcessorCallback)

foreign import ccall unsafe "addHeaderToResponse"
addHeaderToResponse
addHeaderToResponse_c
:: Ptr TResponse -> CString -> CSize -> CString -> CSize -> IO ()
15 changes: 0 additions & 15 deletions server/cpp/HaskellProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,6 @@ void HaskellAsyncProcessor::run(
(*cb)(
context->getHeader()->getProtocolId(), input_data, input_len, &response);
std::unique_ptr<uint8_t[], decltype(free)*> output_str(response.data, free);
SCOPE_EXIT {
free(response.ex_name);
free(response.ex_text);
};
if (response.ex_name) {
auto header = context->getHeader();
header->setHeader(
kUex, std::string(response.ex_name, response.ex_name_len));
if (response.ex_text) {
header->setHeader(
kUexw, std::string(response.ex_text, response.ex_text_len));
}
header->setHeader(
kEx, response.client_error ? kAppClientErrorCode : kAppServerErrorCode);
}

for (auto& hdr : response.headers) {
context->getHeader()->setHeader(hdr.first, hdr.second);
Expand Down
5 changes: 0 additions & 5 deletions server/cpp/HaskellProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ namespace thrift {
struct TResponse {
uint8_t* data;
size_t len;
char* ex_name = nullptr;
size_t ex_name_len = 0;
char* ex_text = nullptr;
size_t ex_text_len = 0;
bool client_error = false;
std::vector<std::pair<std::string, std::string>> headers = {};
};

Expand Down

0 comments on commit 718c604

Please sign in to comment.