Using IdHttp and IdConnectionIntercept created at runtime [duplicate] - multithreading

Delphi6 and XE3.
I want to get the real response body of a request.
But the server makes error 500.
Then the Indy replace the response text with the description of the error.
This homepage is designed for answer 500 in non abnormal operations too, and we need to determine what to do from response text.
Could I get the response text from IdHTTP or from an Exception object when the status code is 500?
Thanks for any info!

When TIdHTTP encounters a server error, it raises an EIdHTTPProtocolException exception, where its ErrorCode property contains the HTTP status code (500, etc), its Message property contains the HTTP status text ("Internal Error", etc), and its ErrorMessage property contains the body text of the response, if any. So, for example:
try
IdHTTP1.Get(...);
except
on E: EIdHTTPProtocolException do begin
// use E.ErrorCode, E.Message, and E.ErrorMessage as needed...
end;
end;

Related

How to display an error message to a user?

I created a like button in my solid-js app that does not allow someone to like a post they authored. For this, I wrote the following code:
const isPostAuthor = postAuthor.authorId === currentUser.id;
if (isPostAuthor) {
return next({
status: 401,
message: "You can`t add a like on your own post"
});
In order to check if the user who likes is the author of the post and to return an error message with status 401 to the user if it is the case. It works fine only that the error message is not displayed to the user instead, it instead displays a red cross to the user; However, this message is displayed on the command line. I thought it was a status error, so I changed the error status 401 to status 400 and then 404 but it still didn't show the error message to the user . So I tried out of curiosity the status 200 used for successful operations, it did return a message to the user but in green color yet the operation failed, I don't know why it works with the success code 200 but not with error codes . Could someone help me?
If my hypothesis is correct based on your explanation, wherever you are receiving this response, you need to add two sections to catch this response, one is success response and the other is error response, because as you said for 200 status code, it is showing the message and indicates the success response, that is the reason you could able to see the message for the user.
You can try adding error section in your code wherever you are receiving this response and see if you could able to catch this user message
hope my hypothesis helps :)

In Express js, how do you properly end a stream response that throws an error

badStream.pipe(res)
When badStream throws an error, the response is not terminating and the request in the browser is stuck in a pending state.
badStream.on(error, function() {this.end()}).pipe(res)
I've tried the above to no avail. What's the proper way to handle the error in this case? Thanks for any help.
In nodejs, an error on the readstream that is piped to the http response stream just unpipes it from the response stream, but does not otherwise do anything to the response stream it was piped to. That leaves it hanging as an open socket with the browser still waiting for it to finish (as you observed). As such, you have to manually handle the error and do something to the target stream.
badStream.pipe(res);
badStream.on('error', err => {
// log the error and prematurely end the response stream
console.log(err);
res.end();
});
Because this is an http response and you are already in the middle of sending the http response body and thus the http status and headers have already been sent, there aren't a lot of things you can do in the middle of sending the response body.
Ultimately, you're going to have to call res.end() to terminate the response so the browser knows the request is done. If there's a content-length header on this response (the length was known ahead of time), then just terminating the response stream before it's done will cause the browser to see that it didn't get the whole response and thus know that something went wrong.
If there's no content-length on the response, then it really depends upon what type of data you're sending. If you're just sending text, then the browser probably won't know there's an error because the text response will just end. If it's human readable text, you could send "ERROR, ERROR, ERROR - response ended prematurely" or some visible text marker so perhaps a human might recognize that the response is incomplete.
If it's some particular format data such as JSON or XML or any multi-part response, then hanging up the socket prematurely will probably lead to a parsing error that the client will notice. Unfortunately, http just doesn't really make provisions for mid-response errors so it's left to the individual applications to detect and handle.
FYI, here's a pretty interesting article that covers a lot about error handling with streams. And, note that using stream.pipeline() instead of .pipe() also does a lot more complete error handling, including giving you one single callback that will get called for an error in either stream and it will automatically call .destroy() on all streams. In many ways, stream.pipeline(src, dest) is meant to replace src.pipe(dest).

How to add custom paramater in error object lb4?

I am using strongloop 4 (lb4). I am facing one issue that in error object I need to one more custom parameter in the error object.
I want it on the global level. On every error, I want to add that custom parameter in every error message.
In loopback4 global error handling is done by src/sequence.ts.
Suppose the error message object is.
{
"error": {
"statusCode": 400,
"name": "xyz",
"message": "firstName is required"
}
}
I want error object output like.
{
"error": {
"customParam" : "customParam",
"statusCode": 400,
"name": "xyz",
"message": "firstName is required"
}
}
Cross-posting the answer I gave on GitHub in https://github.com/strongloop/loopback-next/issues/1867#issuecomment-434247807
Building HTTP error responses is a tricky business. It's easy to get it wrong and open your application to attacks.
In LoopBack (both 3.x and 4.x), we use our strong-error-handler middleware to take care of this. See Handling Errors in our docs.
Here are the important security constraints to keep in mind:
In production mode, strong-error-handler omits details from error responses to prevent leaking sensitive information:
For 5xx errors, the output contains only the status code and the status name from the HTTP specification.
For 4xx errors, the output contains the full error message (error.message) and the contents of the details property (error.details) that ValidationError typically uses to provide machine-readable details about validation problems. It also includes error.code to allow a machine-readable error code to be passed through which could be used, for example, for translation.
In debug mode, strong-error-handler returns full error stack traces and internal details of any error objects to the client in the HTTP responses.
Now that I have warned you, LoopBack 4 makes it very easy to format the error messages your way. Just provide a custom implementation of the Sequence action reject. See Customizing Sequence Actions in our docs, it explain how to create a custom send action. The solution for reject is pretty much the same, you just need a different signature for the action function.
export class CustomRejectProvider implements Provider<Reject> {
// ...
action({request, response}: HandlerContext, error: Error) {
// handle the error and send back the error response
// "response" is an Express Response object
}
}
Caveat: some errors thrown by LB4 have only code set, these errors need a bit of pre-processing to decide what HTTP status code they should trigger. (For example, the error code ENTITY_NOT_FOUND should be mapped to the status code 404). The built-in reject action does not yet expose this pre-processing for consumption by custom reject actions. It's an oversight on our side, l created a new issue https://github.com/strongloop/loopback-next/issues/1942 to keep track of that.
I tried adding error object into new object.
let error = new Error();
error.name = 'Invalid_OTP_AttemptsError';
error.status = 422;
error.message = 'You’ve exceeded the maximum number of One-Time Password (OTP) attempts';
let data={...error};
data.retryCount=foundMb.retryCount
data.resendCount=foundMb.resendCount
return callback(null,data);

Raise Exception from response message

How to raise an exception from the response message e.g {'status': "insufficient credit"}
try:
new_order = api.request(r)
except as :
print(new_order['status'])
else:
print(new_order)
The response message has different key/values when successful/unsuccessful.
I would need to know what api.request is to answer your question exactly.
Without know what it is, I would suggest using traceback with the error, which is in the standard python library.
for example:
import traceback
try:
new_order = api.request(r)
except Exception as err:
print(err)
traceback.print_exc()
else:
print(new_order)
Also, if api.request is raising an exception, it wouldn't be related to any "status message" they send. If they are telling you about the error, then api.result will likely return an object/list with the status code and/or error message in it, and not raise an exception on your server (which I don't think is possible for them to do).
Think of it like this: your server side code executes api.request, which is probably either a GET or POST request to the api's server. If there was an error in your request, they will send you a message saying what the problem is (I assume). No where in this process will an exception be raised.
If the request is sent to their server, there shouldn't be any exceptions raised on your server.
an exception is raised when you call raise 'some exception here', or when there is a syntax error/other serious error. In either case, your code execution is immediately stopped, and your server would respond to your client with a 500 internal service error.

Java exception: "Can't get a Writer while an OutputStream is already in use" when running xAgent

I am trying to implement Paul Calhoun's Apache FOP solution for creating PDF's from Xpages (from Notes In 9 #102). I am getting the following java exception when trying to run the xAgent that does the processing --> Can't get a Writer while an OutputStream is already in use
The only changes that I have done from Paul's code was to change the package name. I have isolated when the exception happens to the SSJS line: var jce: DominoXMLFO2PDF = new DominoXMLFO2PDF(); All that line does is instantiate the class, there is no custom constructor. I don't believe it is the code itself, but some configuration issue. The SSJS code is in the beforeRenderResponse event where it should be, I haven't changed anything on the xAgent.
I have copied the jar files from Paul's sample database to mine, I have verified that the build paths are the same between the two databases. Everything compiles fine (after I did all this.) This exception appears to be an xpages only exception.
Here's what's really going on with this error:
XPages are essentially servlets... everything that happens in an XPage is just layers on top of a servlet engine. There are basically two types of data that a servlet can send back to whatever is initiating the connection (e.g. a browser): text and binary.
An ordinary XPage sends text -- specifically, HTML. Some xAgents also send text, such as JSON or XML. In any of these scenarios, however, Domino uses a Java Writer to send the response content, because Writers are optimized for sending Character data.
When we need to send binary content, we use an OutputStream instead, because streams are optimized for sending generic byte data. So if we're sending PDF, DOC/XLS/PPT, images, etc., we need to use a stream, because we're sending binary data, not text.
The catch (as you'll soon see, that's a pun) is that we can only use one per response.
Once any HTTP client is told what the content type of a response is, it makes assumptions about how to process that content. So if you tell it to expect application/pdf, it's expecting to only receive binary data. Conversely, if you tell it to expect application/json, it's expecting to only receive character data. If the response includes any data that doesn't match the promised content type, that nearly always invalidates the entire response.
So Domino in its infinite wisdom protects us from making this mistake by only allowing us to send one or the other in a single request, and throws an exception if we disobey that rule.
Unfortunately... if there's any exception in our code when we're trying to send binary content, Domino wants to report that to the consumer... which tries to invoke the output writer to send HTML reporting that something went wrong. Except we already got a handle on the output stream, so Domino isn't allowed to get a handle on the output writer, because that would violate its own rule against only using one per response. This, in turn, throws the exception you reported, masking the exception that actually caused the problem (in your case, probably a ClassNotFoundException).
So how do we make sure that we see the real problem, and not this misdirection? We try:
try {
/*
* Move all your existing code here...
*/
} catch (e) {
print("Error generating dynamic PDF: " + e.toString());
} finally {
facesContext.responseComplete();
}
There are two reasons this is a preferred approach:
If something goes wrong with our code, we don't let Domino throw an exception about it. Instead, we log it (instead of using print to send it to the console and log, you could also toss it to OpenLog, or whatever your preferred logging mechanism happens to be). This means that Domino doesn't try to report the error to the user, because we've promised that we already reported it to ourselves.
By moving the crucial facesContext.responseComplete() call (which is what ultimately tells Domino not to send any content of its own) to the finally block, this ensures it will get executed. If we left it inside the try block, it would get skipped if an exception occurs, because we'd skip straight to the catch... so even though Domino isn't reporting our exception because we caught it, it still tries to invoke the response writer because we didn't tell it not to.
If you follow the above pattern, and something's wrong with your code, then the browser will receive an incomplete or corrupt file, but the log will tell you what went wrong, rather than reporting an error that has nothing to do with the root cause of the problem.
I almost deleted this question, but decided to answer it myself since there is very little out on google when you search for the exception.
The issue was in the xAgent, there is a line importPackage that was incorrect. Fixing this made everything work. The exception verbage: "Can't get a Writer while an OutputStream is already in use" is quite misleading. I don't know what else triggers this exception, but an alternative description would be "Java class ??yourClass?? not found"
If you found this question, then you likely have the same issue. I would ignore what the exception actually says, and check your package statements throughout your application. The java code will error on its own, but your SSJS that references the java will not error until runtime, focus on that code.
Update the response header after the body can solve this kind of problem, example :
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.getWriter().write("<html><body>...</body></html>");
response.setContentType("text/html");
response.setHeader("Cache-Control", "no-cache");
response.setCharacterEncoding("UTF-8");

Resources