I wanna get the status code of "www.google.com" by these codes:
final HttpClient client = new DefaultHttpClient();
final HttpPost method = new HttpPost("http://www.google.com");
try {
HttpResponse response = client.execute(method);
int code = response.getStatusLine().getStatusCode();
Log.i("LOG", "Code : " + code);
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
but it gives me the code "405" means we have a problem.
what's the problem with this code?
give me another code to do the same job.but please a simple code. I'm a begginer :)
By the way
I've heard httpclient is deprecated.
I do not believe www.google.com let's you do a POST. That end-point likely only accepts GET requests.
Try googling for a website that accepts dumpy posts. Or standup a test website that accepts POSTs. That should be pretty easy using node.js.
Related
I have an ssh manager to execute (bash) scripts on a server. It contains a commandWithContinousRead(String command, Consumer<String> consumer). Whenever an echo is called in the bash script it is consumed by the consumer. I want to extend this with Spring Boot and an HTTP call. When a client sends a request, the server streams the data when it's ready from a bash script and the client can print it out.
I know Server-Sent Events, however, I feel like that is mostly for events and usually uses multiple resources on an API.
Additionally, I tried searching for streaming topics, but had no success. I did find StreamingResponseBody from Spring, but it collects all the data and then sends it all at once.
I used Postman for testing, maybe it cannot handle streaming?
However, how do I test this?
Example:
#/bin/bash
# Scriptname: stream-this.sh
echo "Starting line"
sleep 4
echo "Middle line"
sleep 4
echo "End line"
Request with commandWithContinousRead, but prints everything at once after eight seconds.
#RequestMapping(value = "/stream-this", method = RequestMethod.POST,
produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public ???? streamScript() {
StreamingResponseBody stream = out -> {
sshManager.commandWithContinousRead("bash /scripts/stream-this.sh", echo -> {
try {
byte[] bytes = echo.getBytes(StandardCharsets.UTF_8);
out.write(bytes);
System.out.println(echo);
} catch (IOException e) {
e.printStackTrace();
}
});
};
return new ResponseEntity<>(stream, HttpStatus.OK);
}
Implementation of commandWithContinousRead function.
public void commandWithContinousRead(String command, Consumer<String> consumer) {
SSHClient client = buildClient();
try (Session session = client.startSession()) {
Session.Command cmd = session.exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(cmd.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = br.readLine()) != null) {
consumer.accept(line);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Now that you have posted the commandWithContinuousRead method, everything looks correct. Also, you've just now stated that you're testing with Postman, and that's definitely a problem -- postman doesn't support streaming responses
https://github.com/postmanlabs/postman-app-support/issues/5040
It's always a good idea to programmatically unit and integration test your code. A simple unit test doesn't even need to use Spring, or a real SSH connection (run the bash script local to the test). The unit test would just be testing the logic of your Consumer and would let you know that the reading of the output, and the bash script itself aren't blocking. Ideally, you would use junit, but here's a simple test class that I put together that shows what I mean.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.lang.Process;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public class Test {
// This would be a #Test instead of a main
public static void main(String... args) {
commandWithContinousRead("bash stream-this.sh", echo -> {
byte[] bytes = echo.getBytes(StandardCharsets.UTF_8);
// assert statements go here
System.out.println("In main -- " + echo);
});
}
public static void commandWithContinousRead(String command, Consumer<String> consumer) {
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
consumer.accept(line);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
An integration test would actually setup Spring, and would go through the endpoint, thereby testing in the same manner that the client/browser would. Commonly, this is done using #WebMvcTest and mockMvc async. You could choose to either mock the SSH client, or to have a server setup explicitly so your actual SSH client can connect to it. (The second option would expose/eliminate issues related to the ssh connection). This kind of test would expose issues with the spring setup/streaming response. You would need to set an artificial timeout on your mock mvc after say, 5 seconds and using a new mock mvc, after 9 seconds That would allow you to see that after 5 seconds, you've received the first echo, and after 9, you have the whole expected response. A good starting point for you would be to look at https://www.tabnine.com/code/java/methods/org.springframework.test.web.servlet.result.RequestResultMatchers/asyncStarted
Having passed those two levels of tests, then you would begin to suspect the client, which in this case, is Postman. If possible, try to use the actual browser(s) or clients that will be running your code. It may turn out that streaming might not be an option for you.
Please post the implementation of commandWithContinousRead
It could be a fundamental problem where the script that is echoing and sleeping is running on the same thread as the code that is supposed to read the echo and print them out. I.e., you're blocking while you wait for the bash script itself to run which would explain the 8 second delay before getting any output. Also, what type does commandWithContinousRead return? Depending, on how you're "reading" the echos in that method, you could be blocking there too. It's hard to say with 100% certainty without seeing the code for commandWithContinousRead.
Your return type will be a ResponseEntity<StreamingResponseBody> (to fill in the ????)
Okay, I came up with a solution that worked. As Pickled Brain mentioned, the main problem was Postman not working with streaming. Also, I went back to try SSE in a single call and I did by running the bash script in another thread. Additionally, I created an SSE client in Nodejs for testing purposes and it worked flawlessly.
Function to run the script, and place it in another thread.
private SseEmitter runScript() {
SseEmitter emitter = new SseEmitter(-1L); // -1L = no timeout
ExecutorService sseMvcExecutor = Executors.newSingleThreadExecutor();
sseMvcExecutor.execute(() -> {
try {
shellManager.commandWithContinousRead("bash scriptname"), s -> {
SseEmitter.SseEventBuilder event = SseEmitter.event().name("message").data(s);
try {
emitter.send(event);
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
});
emitter.send(SseEmitter.event().name("close").data(""));
} catch (IOException e) {
e.printStackTrace();
}
emitter.complete();
});
return emitter;
}
SSE Client:
const EventSource = require('eventsource'); // npm install eventsource
const url = 'yoururl';
var es = new EventSource(url);
es.onopen = function(ev) {
console.log("OPEN");
console.log(ev);
};
es.onmessage = function(ev) {
console.log("MESSAGE");
console.log(ev.data);
};
es.addEventListener('close', function() {
es.close();
console.log('closing!');
});
es.onerror = function(ev) {
console.log("ERROR");
console.log(ev);
es.close();
};
process.on('SIGINT', () => {
es.close();
console.log(es.CLOSED);
});
I'm trying to do repeat payments with Form Integration in Sagepay (now Opayo).
From an earlier problem posted on here, I get that the securitykey is needed but is not returned in the Form call, so an additional call needs to be made to the getTransactionDetails command.
I have the securitykey and can now make a call to https://test.sagepay.com/gateway/service/repeat.vsp to initiate the repeat payment. However, the documentation does not say where the response to that call goes. I assume therefore, that it would go to the NotificationURL that is set up with a payment when using the Server or Direct integrations. Since I'm using Form, this is not set.
The question is, is there any way of capturing the response to the https://test.sagepay.com/gateway/service/repeat.vsp call if the initial payment was created using Form integration?
I suppose the second question is, has anybody successfully made repeat payments work with Sagepay Form integration?
Not sure if this helps you and we didn't do repeat payments; but we are looking at releasing deferred payments and I think it is a similar approach.
How do you make the call to 'https://test.sagepay.com/gateway/service/repeat.vsp'?
Could you use a 'HttpWebRequest' to make the call then capture the direct response in 'HttpWebResponse'?
EG:
private static void DeferredSharedApiCall(Dictionary<string, string> data, string type, string url)
{
string postData = string.Join("&", data.Select(x => $"{x.Key}={HttpUtility.UrlEncode(x.Value)}"));
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (TextWriter tw = new StreamWriter(request.GetRequestStream()))
{
tw.Write(postData);
}
HttpWebResponse response = null;
try
{
response = request.GetResponse() as HttpWebResponse;
}
catch (WebException ex)
{
//log.Error($"{type} Error, data: {postData}", ex);
}
catch (Exception ex)
{
//log.Error($"{type} Error, data: {postData}", ex);
}
if (response != null)
{
using (TextReader tr = new StreamReader(response.GetResponseStream()))
{
string result = tr.ReadToEnd();
//log.Info($"{type} Response: {Environment.NewLine}{result}");
}
}
}
To start off with, this might be tagged as a duplicate of the following thread:
Wait for HttpWebRequest.BeginGetResponse to finish in Windows Phone 7, however, the responses in that thread did not help me get over my problem.
To begin with, I am collecting user data on the UI Thread in order to process application registration, where I also have an instance of ManualResetEvent:
private static ManualResetEvent registrationEvent = new ManualResetEvent(false);
I have another thread which handles the registration process (and includes the HttpWebRequest.BeginGetResponse() and its corresponding callback method.)
Thread t = new Thread(() => RegistrationHandler.sendRegistrationData(url));
t.Start();
Right after this call, I block the current (UI) thread with a call to
registrationEvent.WaitOne();
//Process the response, update some UI elements and navigate to a different page.
httpSessionCompleted(response);
Once the thread handling the registration process starts, I am instantiating HttpWebRequest and invoking the BeginGetResponse() method on it.
try
{
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.Method = "POST";
request.ContentType = mimeType;
request.BeginGetResponse(new AsyncCallback(GetRequestCallback), request);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in sendData(): {0}", ex.Message);
}
Now the issue is that the callback method (code below) is never invoked, and the application just freezes. There also doesn't seem to be any exception(s) thrown either.
try
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
if (request != null)
{
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
String result = reader.ReadToEnd();
Globals.HostResponse = result;
//Signalling the calling thread to continue execution
RegistrationPage.RegistrationEvent.Set();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in GetRequestCallback(): {0}", ex.Message);
}
I ideally want my application to continue from httpSessionCompleted() after the callback method finishes execution. Can someone please help me with some guidance/suggestions?
Sorry for being verbose. Thanks!
You should not block UI thread, use callback pattern instead. Look at this: Windows Phone 7 - wait for Webclient to complete . Hope this helps
I'm trying to make an App for windows phone 7. This app will basiclly retrive information from a website that we use at work as our working schedule then rearrange the retrived info into a metro style UI. To be honest i don't know where to start ie. how to retrive the info. Should i use webclient class? httpwebrequest class? or something else?
All idea are appriciated
Here is a:-
Update:-
Okay either im totally stupid or there is something wrong with the code i'm writing, that i can't figure it out. I was using the same code that you wrote BUT i still get an error that a definition for Proxy is not in the System.Net.WebRequest :( This is my code (the working version):-
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
App.ViewModel.LoadData();
}
string url = "https://medinet.se/*****/schema/ibsef";
WebRequest request = WebRequest.Create(url);
request.BeginGetResponse(new AsyncCallback(ReadWebRequestCallBack), request);
}
private void ReadWebRequestCallBack(IAsyncResult callbackResult)
{
try
{
WebRequest myRequest = (WebRequest)callbackResult.AsyncState;
WebResponse myResponse = (WebResponse)myRequest.EndGetResponse(callbackResult);
using (StreamReader httpwebStreamReader = new StreamReader(myResponse.GetResponseStream()))
{
string results = httpwebStreamReader.ReadToEnd();
Dispatcher.BeginInvoke(() => parsertextBlock.Text = results);
}
myResponse.Close();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
Dispatcher.BeginInvoke(() => parsertextBlock.Text = ex.ToString());
}
}
But if i add request.Proxy=null!! i get an error, that there is no definition for Proxy in (System.Net.WebRequest). And to be honest i start getting mad of this.
Yours
/Omar
The process is called ScreenScrape and i recommend you to use Html Agility Pack http://htmlagilitypack.codeplex.com/ . Make a web service that retrieves the information from your website and rearranges to appropriate format. Use your web service by a phone and display your data.
Use WebRequest ( http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx) and WebResponse ( http://msdn.microsoft.com/en-us/library/system.net.webresponse(v=vs.100).aspx) .
TIP: Set the WebRequest.Proxy property ( http://msdn.microsoft.com/en-us/library/system.net.webrequest.proxy.aspx) to null, as i find it will be much faster.
UPDATE: More info on WebRequest Proxy property
Set Proxy = null on the WebRequest object to avoid an initial delay (that way the request won't start auto detecting proxies, which i find it's faster).
WebRequest req = WebRequest.Create("yourURL");
req.Proxy = null;
It's in the System.Net namespace so put an using statement using System.Net; or
System.Net.WebRequest req = WebRequest.Create("yourURL");
req.Proxy = null;
Regards.
I try to get my code working with catching certain errors. I store the token for a user after he or she grants permission to my app (this is a WP7 app). When I try to post on the wall by using the stored token it works. When I remove the permissions on facebook it throws an OAuthException. I can't catch it it seems. My app just crashes. This is the code I used:
private object PostToFacebook()
{
_fbApp = new FacebookClient(_appsettings.faceBookToken);
FacebookAsyncCallback callback = new FacebookAsyncCallback(this.postResult);
var parameters = new Dictionary<string, object>();
parameters.Add("message", "message on wall");
try
{
_fbApp.PostAsync("me/feed", parameters, callback);
}
catch (Exception ex)
{
}
return null;
}
private void postResult(FacebookAsyncResult asyncResult)
{
if (asyncResult.Error == null)
{
status = "succes";
}
else
{
status = "error" + asyncResult.Error.Message;
}
}
The try catch doesn't catch anything and the generic exception handler in my app.xaml.cs either.
Any ideas how to catch this error so I can ask the user to authenticate again?
Put your try..catch in the callback.
You can also catch exceptions globally by handling the UnhandledException event on the App object.