I want to deliver a soap message by HTTPS/Post by specifying Content-Type application/HTTPstream and the following custom HTTP-headers
datatype = 'XML' userid= password
I tried with CALL CopyMessageHeaders();
SET OutputRoot.HTTPRequestHeader."Content-Type" = 'application/HTTPstream';
and other part same as this but I am not getting Headers in my output message
Related
I am trying to add multiple host header for post http request on postman , but I am getting error like Error: hostHeader.startsWith is not a function .
If I pass single header it is working , but if I pass one more header it is throwing the error could not send the request with the above message.
Is there any configuration I need to have to allow multiple host headers
The official documentation does not provide an example for any SDK's (including the Java SDK): https://learn.microsoft.com/en-us/graph/api/user-sendmail?view=graph-rest-1.0&tabs=java#example-4-send-a-new-message-using-mime-format. As there is no example, I have tried in vain to send the MIME content using the SDK (microsoft-graph 5.0.0):
Message sending = new Message();
ItemBody body = new ItemBody();
final String mimeMessageRFC822 = input.getMimeMessageRFC822();
body.content = Base64.getMimeEncoder().encodeToString(mimeMessageRFC822.getBytes());
sending.body = body;
GraphServiceClient service = getService(acHost, configuration);
service
.me()
.sendMail(UserSendMailParameterSet.newBuilder().withMessage(sending).withSaveToSentItems(true).build())
.buildRequest(new HeaderOption("Content-Type", "text/plain"))
.post();
The above code sets the request's content-type to text/plain, however the request body that is being sent is JSON (xxxxxx below is a placeholder for a valid Base64 encoded MIME content string).
{
"message":
{
"body":
{
"content": xxxxxx
}
},
"saveToSentItems": true
}
The response is a 404, stating:
GraphServiceException: Error code: ErrorMimeContentInvalidBase64String
Error message: Invalid base64 string for MIME content.
I can understand why it is responding with this error as the graph endpoint is parsing the text/plain content as base64 encoded MIME but finds the JSON structure instead. I have been on a video call with a Microsoft Graph support agent, and they have seen that my MIME content is valid. Sadly, they are not able to help with the Microsoft Graph Java SDK even though it is developed by Microsoft!
This suggests that we are not supposed to use the Java SDK at all for sending MIME formatted emails. Is this correct? Surely it can't be otherwise what is the point of a library that can receive MIME formatted emails but can't send them? Does anyone have a solution?
For now at least the solution is to send a CustomRequest with MIME content instead of using the fluent API provided by the Graph client.
final String encodedContent = Base64.getMimeEncoder().encodeToString(mimeMessageRFC822.getBytes());
CustomRequest<String> request = new CustomRequest<>(requestUrl, service, List.of(new HeaderOption("Content-Type", "text/plain")), String.class);
request.post(encodedContent);
When i POST a request to my .net core 2 mvc backend it returns json data.
I want to optionally change the headers as so , which i will then return a csv file of the data for download
'Accept': 'text/csv',
'Content-Type': `text/csv; charset=utf-8`
I set the controller base class with this Produces filter
[Produces("application/json", "text/csv")]
But those headers always cause .net to return 415 Unsupported Media Type
The controller action looks like this
[HttpPost]
public async Task<IActionResult> Post([FromBody] PostArgs args)
You source of problem is Content-Type: text/csv; charset=utf-8 header.
[FromBody] forces MVC middleware to use the input formatter for model binding (I am talking about PostArgs model). And by default, ASP.NET Core registers only one, JSON input formatter. Cause you set Content-Type, middleware cannot use that default formatter (as Content-Type header says that data in request body should be processed as CSV, not JSON) and so it throws 415 Unsupported Media Type error.
... I want to optionally change the headers as so , which i will then return a csv file of the data for download
Actually, it looks like you understand in wrong way what Content-Type header does:
In requests, (such as POST or PUT), the client tells the server what type of data is actually sent.
In other words, you only need to specify the Accept header, cause
The Accept request HTTP header advertises which content types, expressed as MIME types, the client is able to understand. Using content negotiation, the server then selects one of the proposals.
And it is the server then, who uses a Content-Type header in responses to tell the client what the content type of the returned content (in response) actually is.
To return csv data, you return a ContentResult rather than a JsonResult object. This allows you to define the Content-Type:
return new ContentResult("csv-data", "text/csv", 200);
If you want to return a physical file you could return a FileResult object.
By default, the Accepts header isn't enforced. You can enforce it via configuration:
services.AddMvc(config =>
{
config.RespectBrowserAcceptHeader = true;
});
In order to accept additional formats, you'll also need to add InputFormatters:
services.AddMvc(config =>
{
config.RespectBrowserAcceptHeader = true;
config.InputFormatters.Add(new TextInputFormatter())
config.OutputFormatters.Add(new StringOutputFormatter());
});
I have a Grails controller that receives a DefaultMultipartHttpServletRequest like so:
def myController() {
DefaultMultipartHttpServletRequest proxyRequest = (DefaultMultipartHttpServletRequest) request
}
This controller acts as a proxy by taking pieces of this request and then resends the request to another destination.
For non-multipart requests, this worked fine, I did something like:
IProxyService service = (IProxyService) clientFactory.create()
Response response = service.doPOST(proxyRequest.getRequestBody())
Where proxyRequest.getRequestBody() contains a JSON block containing the request payload.
However, I do not know how to get this to work with multipart request payload, since the request body is no longer a simple block of JSON, but something like the following (taken from Chrome devtools):
How can I can pass this request payload through using my proxy service above, where doPost takes a String?
Have you tried
def parameterValue = request.getParameter("parameterName")
to get the parameter value?
If you see the method signatures for DefaultMultipartHttpServletRequest you will see there are methods for getting the files and other parameters separately because the request body is getting used to both upload the file and to pass in other parameters.
I have a Rails app and I have implemented api using Grape gem. Now, I created a custom error formatter (CSVFormatter) to return error response in CSV format.
And, also I have this in my application's v2.rb file:
error_formatter :csv, Api::Base::Errors::CSVFormatter
When I hit a url like this:
http://example.com/api/v2/datasets/CODE/data.csv?&trim_start=06/01/99&trim_end=2014-05/28&sort_order=desc
It shows the error in the console like this which is good and means that my custom error formatter is working properly:
Error
trim_start is invalid
trim_end is invalid
But, I just need to download this error message in a csv file. After looking at Grape's documentation, I found a way of setting Content-type and I tried this:
rack = Rack::Response.new(as_csv , 422, { "Content-type" => "text/csv" }).finish
rack[2].body[0]
But, this is not working as I expected.
EDIT:
Looks like there is no clean way of doing it using grape without forcefully overriding the status code according to the answer of Simon. But, one may not wish to do that as it may result other issues in the application like if some other program tries to read the data from the api and gets the incorrect response or so even without knowing why.
You're looking for the Content-Disposition header. Include it in your response like this:
Content-Disposition: attachment; filename=error.csv
And the Web browser will treat the response body as a file to be downloaded (to "error.csv", in this example).
However, modifying your code to do this is complicated by two things:
From the Grape source code it's apparent there's no way to set response headers from within an error formatter, so you'll need to add a custom exception handler that formats the response body and sets the response headers appropriately for each output format you plan to support.
According to my experimentation, browsers will ignore the Content-Disposition header if the HTTP status code indicates an error (e.g. anything in the 400 or 500 range), so the status code will also need to be overridden when the user requests a CSV file.
Try adding this to your API class:
# Handle all exceptions with an error response appropriate to the requested
# output format
rescue_from :all do |e|
# Edit this hash to override the HTTP response status for specific output
# formats
FORMAT_SPECIFIC_STATUS = {
:csv => 200
}
# Edit this hash to add custom headers specific to each output format
FORMAT_SPECIFIC_HEADERS = {
:csv => {
'Content-Disposition' => 'attachment; filename=error.csv'
}
}
# Get the output format requested by the user
format = env['api.format']
# Set the HTTP status appropriately for the requested output format and
# the error type
status = FORMAT_SPECIFIC_STATUS[format] ||
(e.respond_to? :status) && e.status ||
500
# Set the HTTP headers appropriately for the requested format
headers = {
'Content-Type' => options[:content_types][format] || 'text/plain'
}.merge(FORMAT_SPECIFIC_HEADERS[format] || { })
# Format the message body using the appropriate error formatter
error_formatter =
options[:error_formatters][format] || options[:default_error_formatter]
body = error_formatter.call(e.message, nil, options, env)
# Return the error response to the client in the correct format
# with the correct HTTP headers for that format
Rack::Response.new(body, status, headers).finish
end
Now if you configure your API class to handle two different formats (I've picked CSV and plain-text here for simplicity), like this:
module Errors
module CSVErrorFormatter
def self.call(message, backtrace, options, env)
as_csv = "CSV formatter:" + "\n"
message.split(",").each do |msg|
as_csv += msg + "\n"
end
# Note this method simply returns the response body
as_csv
end
end
module TextErrorFormatter
def self.call(message, backtrace, options, env)
as_txt = "Text formatter:" + "\n"
message.split(",").each do |msg|
as_txt += msg + "\n"
end
as_txt
end
end
end
content_type :csv, 'text/csv'
content_type :txt, 'text/plain'
error_formatter :csv, Api::Base::Errors::CSVErrorFormatter
error_formatter :txt, Api::Base::Errors::TextErrorFormatter
You should find your API always returns an error response suitable for the requested format, and triggers the browser to download the response only when CSV format is requested. Naturally this can be extended to support as many formats as you like, by explicitly declaring content types and error formatters.
Note there's one case in which this code doesn't automatically do the right thing, and that's when an error response is invoked directly using error!. In that case you'll have to supply the correct body and headers as part of the call itself. I'll leave extracting the relevant parts of the above code into reusable methods as an exercise for the reader.