failed to fetch using spring api on localhost - javascript

The javascript tries to fetch data from my spring boot api and gives back a "Failed to fetch" error everytime.
I'm sure the request reaches the api because for every click on submit I get the print statement, that i put in my get method, logged as it should. So something on the way back must be wrong.
Get method:
#RestController
#RequestMapping("/familyMember")
public class FamilyController {
private FamilyRepository familyRepository;
public FamilyController(FamilyRepository familyRepository) {
this.familyRepository = familyRepository;
}
#GetMapping("/id/{id}")
public FamilyMember getById(#PathVariable("id") Long id) {
Optional<FamilyMember> optional = familyRepository.findById(id);
if (!optional.isPresent()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
}
FamilyMember familyMember = optional.get();
System.out.println(id); //print statement to make sure api is reached
return familyMember;
}
Javascript code:
const url = 'http://localhost:4001/familyMember/';
submit.onclick = async() => {
const endpoint = url + 'id/' + input.value;
try {
const response = await fetch(endpoint); // error occures here because no code below is executed
output.style.color = 'green'; // to see if fetch continues(apparently it doesn't)
if (response.ok) {
output.innerHTML += await response.json();
}
} catch(error) {
output.innerHTML += error; // gives me "Failed to fetch" in the html
}
I'm not sure if the bug is on the server side or client side. The api gives me the correct information when I use curl in the terminal...so propably the js code?
Thanks in advance.

Actually found the answer. Above #RestController I need the annotation #CrossOrigin sothat the api allows requests from different origins than itself (in that case a html file).
#CrossOrigin
#RestController
#RequestMapping("/familyMember")
public class FamilyController {
...

You should specify cross origin with an adress like "localhost:4001"

Related

converting data url to a format that I can use to send to my backend web api and store in database

I am currently getting drag and drop / uploaded images as a data url and displaying them with that url.
What I am now trying to do is send those uploaded images to my backend web api using ASP.Net core to store then in a sqlite database this is a requirement for my application.
Currently I am converting the data url to an arraybuffer using the following code.
async srcToFile(context, asset) {
const files = asset[0].files.fileList;
let results = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
const data = file.data;
const name = file.name;
const mimeType = file.type;
await fetch(data)
.then(function(res) {
const r = res.arrayBuffer();
console.warn('resource ', r);
return r;
})
.then(function(buf) {
console.warn('buffer: ', [buf]);
const fileData = {data:[buf], name:name, type:mimeType};
results.push(fileData);
console.warn('results of file: ', fileData);
});
}
console.warn(results);
return results;
}
then I put it in an data object to send to my server via axios this is what that data object looks like
const data = {
Name: asset[0].name,
Detail: asset[0].detail,
Files: asset[0].files.fileList
};
When I console out the Files it shows there is Arraybuffer data in it. But when I send it to my server it looks like that data is stripped out of the header call. Cause when I look at the header I no longer have that data in there and I cannot figure out why that is happening.
this is my axios call.
axios.post('https://localhost:5001/api/Assets', data)
.then(res => console.log(res))
.catch(error => console.log(error));
and my back end web api post controller
public async Task<ActionResult> PostAsset([FromBody] AssetSaveRequest request,[FromForm] List<IFormFile> files)
{
foreach (var file in files)
{
if (file.Length > 0)
{
using (var ms = new MemoryStream())
{
file.CopyTo(ms);
var fileBytes = ms.ToArray();
string s = Convert.ToBase64String(fileBytes);
// act on the Base64 data
}
}
}
var assetCreationDto = new AssetCreationDto(request);
//var assetCreationDto = "";
try
{
var asset = _mapper.Map<Asset>(assetCreationDto);
_context.Assets.Add(asset);
//await _context.SaveChangesAsync();
var assetDto = _mapper.Map<AssetDto>(asset);
return CreatedAtAction("GetAsset", new {assetDto.Id}, assetDto);
}
catch (DbUpdateException dbe)
{
var errorCode = ((Microsoft.Data.Sqlite.SqliteException) dbe.InnerException).SqliteErrorCode;
switch (errorCode)
{
case 19:
Console.WriteLine(((Microsoft.Data.Sqlite.SqliteException)dbe.InnerException).Message);
break;
default:
Console.WriteLine("Something went wrong");
break;
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
return null;
}
That of which I don't know is working because I never get the file data, I do how ever get the Name and the details which come in fine.
I am looking for advice on what I should do here to get this to work. I have tried converting the arraybuffer to base64 string but that does not come out right any help and suggestions would be great to get me back on track with this project .
UPDATE:
I have modified my srcToFile code to give me a file, now I am using axios to send the file and data to the backend working with one file at this time and all im getting in the header now is [object object]. I've tried JSON.stringify on my data like so
const data = JSON.stringify({
Name: asset[0].name,
Detail: asset[0].detail,
Files: asset[0].files.fileList
});
It stringify's the name and detail but wipes out the file and I get nothing on the backend.
I have tested with postman and made several successful posts. but I can't seem to get the correct data from my Vue front end.
that is where I am at now. any suggestions always helps

sending an AJAX request for an audio blob to an async API

I'm working on a legacy system and I'm trying to call an HTTP handler which I have added some logic which retrieves audio blob from an Azure service.
The thing is, I can't seem to get the content back to the client so I can play it.
The response that I get from a jQuery call is:
"System.Threading.Tasks.Task`1[System.String]"
This is the processRequest code:
public void ProcessRequest(HttpContext context)
{
var text = "walk";
Authentication auth = new Authentication("subscriptionID");
context.Response.Write(auth.getVoice(text));
}
Here's the getVoice function:
public async Task<string> getVoice(string text)
{
using (var client = new HttpClient())
{
try
{
client.DefaultRequestHeaders
.Add("User-Agent", "uagent");
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + this.token);
client.DefaultRequestHeaders.Add("host", "westeurope.tts.speech.microsoft.com");
client.DefaultRequestHeaders.Add("X-MICROSOFT-OutputFormat", "audio-16khz-32kbitrate-mono-mp3");
UriBuilder uriBuilder = new UriBuilder(VoiceUri);
// send xml post
var voiceTest = "<speak version='1.0' xml:lang='en-US'><voice xml:lang='en-US' xml:gender='Female'\n\rname='Microsoft Server Speech Text to Speech Voice (en-US, ZiraRUS)'>\n\rWalk\n\r</voice></speak>";
var data = new StringContent(voiceTest, Encoding.UTF8, "application/xml");
data.Headers.ContentType = new MediaTypeHeaderValue("application/ssml+xml");
var result = await client.PostAsync(uriBuilder.Uri.AbsoluteUri, data);
return await result.Content.ReadAsStringAsync();
}
catch (Exception e)
{
return null;
}
}
The server API call is successful but I can't seem to receive it on the client side in order to play it to the user afterward.
You have to unwrap the result of auth.getVoice. You can do it by using await key word. Also you need you handler to implement HttpTaskAsyncHandler class in order to make it work
public class TestHandler : HttpTaskAsyncHandler
{
public async override Task ProcessRequestAsync(HttpContext context)
{
var text = "walk";
Authentication auth = new Authentication("subscriptionID");
context.Response.Write(await auth.getVoice(text)); //added await here
}
//..
}

Capture REST calls with Selenium

I run integration test with Selenium as a test runner and webdriver.io javascript library for Selenium API.
My test goes as follows:
I load an html page and click on a button. I want to check if a Get REST call was invoked.
I found a plugin for webdriver.io called webdriverajax that intend to fit to my requirements but it just doesn't work.
Any ideas how do capture rest calls?
You can achieve this by using custom HttpClient class that is out side from selenium code.As far as i know selenium doesn't support this feature.
Assume when you clicked the button it will called a REST service , the URL can be grab from the HTML DOM element.Then you can use your custom code to verify if URL is accessible or not.Then you can decide if your test is pass or failed based on the status code or some other your mechanism.
FileDownloader.java(Sample code snippet)
private String downloader(WebElement element, String attribute) throws IOException, NullPointerException, URISyntaxException {
String fileToDownloadLocation = element.getAttribute(attribute);
if (fileToDownloadLocation.trim().equals("")) throw new NullPointerException("The element you have specified does not link to anything!");
URL fileToDownload = new URL(fileToDownloadLocation);
File downloadedFile = new File(this.localDownloadPath + fileToDownload.getFile().replaceFirst("/|\\\\", ""));
if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);
HttpClient client = new DefaultHttpClient();
BasicHttpContext localContext = new BasicHttpContext();
LOG.info("Mimic WebDriver cookie state: " + this.mimicWebDriverCookieState);
if (this.mimicWebDriverCookieState) {
localContext.setAttribute(ClientContext.COOKIE_STORE, mimicCookieState(this.driver.manage().getCookies()));
}
HttpGet httpget = new HttpGet(fileToDownload.toURI());
HttpParams httpRequestParameters = httpget.getParams();
httpRequestParameters.setParameter(ClientPNames.HANDLE_REDIRECTS, this.followRedirects);
httpget.setParams(httpRequestParameters);
LOG.info("Sending GET request for: " + httpget.getURI());
HttpResponse response = client.execute(httpget, localContext);
this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
LOG.info("HTTP GET request status: " + this.httpStatusOfLastDownloadAttempt);
LOG.info("Downloading file: " + downloadedFile.getName());
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
response.getEntity().getContent().close();
String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
LOG.info("File downloaded to '" + downloadedFileAbsolutePath + "'");
return downloadedFileAbsolutePath;
}
TestClass.java
#Test
public void downloadAFile() throws Exception {
FileDownloader downloadTestFile = new FileDownloader(driver);
driver.get("http://www.localhost.com/downloadTest.html");
WebElement downloadLink = driver.findElement(By.id("fileToDownload"));
String downloadedFileAbsoluteLocation = downloadTestFile.downloadFile(downloadLink);
assertThat(new File(downloadedFileAbsoluteLocation).exists(), is(equalTo(true)));
assertThat(downloadTestFile.getHTTPStatusOfLastDownloadAttempt(), is(equalTo(200)));
// you can use status code to valid the REST URL
}
Here is the reference.
Note: This may not exactly fit into your requirement but you can get some idea and modify it accordingly to fit into your requirement.
Also refer the BrowserMob Proxy using this you can also achieve what you want.
The problem was the webdriver.io version. Apparently, webdriverajax works fine just with webdriver.io v3.x but not with v4.x. I use v4.5.2.
I decide not using a plugin and implement a mock for window.XMLHttpRequest
open and send methods, as follows:
proxyXHR() {
this.browser.execute(() => {
const namespace = '__scriptTests';
window[namespace] = { open: [], send: [] };
const originalOpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (...args) {
window[namespace].open.push({
method: args[0],
url: args[1],
async: args[2],
user: args[3],
password: args[4]
});
originalOpen.apply(this, [].slice.call(args));
};
window.XMLHttpRequest.prototype.send = function (...args) {
window[namespace].send.push(JSON.parse(args[0]));
};
});
}
getXHRsInfo() {
const result = this.browser.execute(() => {
const namespace = '__scriptTests';
return window[namespace];
});
return result.value;
}

Issue Parsing JSON Response

I'm using AJAX/JQuery to call a WCF service. I have some .NET try/catch error-handling on the service-side that checks to see if the user has timed out, and if they have then I pass back a JSON-converted message which I then parse out on the client-end using parseJSON and use it to re-direct the user back a login page.
This is all working great, but I just got a different type of error returned from the service that WASN'T in JSON format (it was XML) so the error-handling function got a javascript error on the client side when it tried to parse the reply. The error was in the jquery.min.js file, and was an 'Invalid character' error.
My question (finally), is there a better way to handle that reply if I can't always rely on it being JSON? In .NET we have a tryParse method available that would work great here, but as far as I know JQuery/Javascript has no such feature. If it can't parse the reply, it throws a JS error.
Here is where the custom JSON exception is thrown:
private HttpSessionState GetUserSession()
{
HttpSessionState session = HttpContext.Current.Session;
try
{
// This is a method we created that checks if user has timed out and throws the exception if so.
SessionBuilder.Create(session, HttpContext.Current.Request, HttpContext.Current.Response);
}
catch (SessionTimeOutException e)
{
throw new WebFaultException<SessionTimeOutException>(new SessionTimeOutException(e.Message), System.Net.HttpStatusCode.BadRequest);
}
return session;
}
And here is the client-side code that handles errors in my AJAX request:
error: function (HttpRequest)
{
// This is the line that gets the exception because the responseText is a standard .NET XML error, not my custom JSON error.
var parsedReply = $.parseJSON(HttpRequest.responseText);
if (parsedReply.ClassName === "SessionTimeOutException")
{
var url = "../timeout.asp?" + parsedReply.Message;
window.location.href = url;
}
}
JavaScript has try { ... } catch(ex) { ... } also.
error: function (HttpRequest)
{
var parsedReply;
try {
parseReply = $.parseJSON(HttpRequest.responseText);
if (parsedReply.ClassName === "SessionTimeOutException")
{
var url = "../timeout.asp?" + parsedReply.Message;
window.location.href = url;
}
} catch(ex) {
parsedReply = HttpRequest.responseText;
//Do something else
}
}

Calling server side function from signalR in Android

SignalR connected in Android, But I want to call a function which is available on server,
I tried the following code,
String host = "Host URL";
HubConnection hubConnection = new HubConnection(host, "", false, new Logger() {
#Override
public void log(String message, LogLevel level) {
System.out.println("message - " + message);
}
});
hubProxy = hubConnection.createHubProxy("Task");
SignalRFuture<Void> signalRFuture = hubConnection.start().done(addSession("Session ID"));
And
private Action<Void> addSession(String sessionID) {
//hubProxy. [server is not available here]
}
In javascript, I tried like following,
$.connection.hub.start().done(function () {
addSession(sessionId)
});
function addSession(sessionId) {
proxy.server.addSession(sessionId)
.done(function () {
isHubConnected = true;
}
);
}
In javascript this works perfectly, But in android :( ,
Update
By trying like #AnikIslamAbhi's answer,
signalRFuture = hubConnection.start().done(addSession("sessionID"));
private Action<Void> addSession(String sessionID) {
System.out.println("addSession : " + sessionID);
hubProxy.invoke("addSession", sessionID);
return null;
}
I received following error message,
InvalidStateException: The operation is not allowed in the 'Connecting' state
In javascript you are using Auto proxy.
But in android you are using manual proxy
Both have differences in their behavior.
Like
To call serverside method using auto proxy
proxy.server.addSession(sessionId)
To call serverside method using manual proxy
proxy.invoke("addSession", sessionId)
You can find more on this link

Categories

Resources