I have a laravel project where i store my data. I want to get this data in my Vue frontend using fetch. But while im trying im getting an Error 500. Why?
This is my mounted function in Vue
mounted(){
fetch("/api/items")
.then((response)=>response.text())
.then((data)=>{
this.msg = JSON.parse(data);
{
Get Function in Laravel
public function index()
{
return Item::orderBy('created_at','DESC')->get();
}
Post function in Laravel
public function store(Request $request)
{
$newItem = new Item;
$newItem->name = $request->item["name"];
$newItem->save();
return $newItem;
}
my Routes
Route::middleware('auth:sanctum')->get('/user', function (Request
$request) {
return $request->user();
});
Route::get('/items', [ItemController::class, 'index']);
Route::prefix('/item')->group(function(){
Route::post('/store', [ItemController::class, 'store']);
Route::put('/{id}', [ItemController::class, 'update']);
Route::delete('/{id}', [ItemController::class, 'destroy']);
});
the Error
I tried it with postman to check if its on my Server or frontend. There i have no problems
Post in Postman
Get in Postman
Related
I work on web application and encountered an issue with fetching data from an endpoint using Java Script. If I type endpoint adres in a browser it works perfectly fine but somehow it does not work in the script. The response.ok is returns False.
Here is script:
(function() {
function requestAuthorization() {
let response = fetch("http://localhost:8080/authorizationData")
.then(response => response.json());
if (response.ok) {
let json = response.json();
alert(json);
} else {
alert("HTTP response not ok");
}
}
requestAuthorization();
})();
Here is controller:
#RestController
class AuthController {
private final AuthService service;
AuthController(AuthService service) throws IOException {
this.service = service;
}
#GetMapping("/authorizationData")
public ResponseEntity<AuthData> authorize() throws IOException {
return ResponseEntity.ok(service.getAuthData());
}
}
Here is service:
#Service
class AuthService {
private final ObjectMapper mapper;
AuthService(ObjectMapper mapper) {
this.mapper = mapper;
}
public AuthData getAuthData() throws IOException {
String resourcePath = "data/applicationSettings.json";
InputStream resource = new ClassPathResource(resourcePath).getInputStream();
return mapper.readValue(resource, AuthData.class);
}
}
What is wrong? If You have any other advice regarding my work I will be pleased to hear it.
EDIT
The script and and HTML file which runs it are both located in static directory in classpath.
You should be doing it like this:
// mark your function as async
async function requestAuthorization() {
// always try using const rather than let
const response = await fetch("http://localhost:8080/authorizationData");
if (response.ok) {
const json = response.json();
alert(json);
} else {
alert("HTTP response not ok");
}
}
On the frontend code, I have a user login form that takes in the values (strings) email and password. In my userstore using MobX State Management, I have an action when a user presses the login button to submit the strings as an HTTP post
#action login = async (values: IUserFormValues) => {
try {
console.log(values);
const user = await agent.User.login(values);
runInAction(() => {
this.user = user;
});
console.log(user);
} catch (error) {
console.log(error);
}
};
}
The Request looks something like this:
const responseBody = (response: AxiosResponse) => response.data;
const requests = {
post: (url: string, body: {}) =>
axios.post(url, body).then(sleep(1000)).then(responseBody),
};
login: (user: IUserFormValues): Promise<IUser> =>
requests.post(`/user/login`, user)
Now to the backend, this is where I am completely lost. Not sure what to build from here:
[HttpPost("login")]
- Here -
I am gonna have to take these values and verify with a database from SQL server. There's just so many different examples using different middleware that I am just not sure what's correct or best practices.
Here is a very nice tutorial from the Microsoft Docs, using Entity Framework (very nice), and some dependency injection (very very nice).
Basically you create an API controller class with your CRUD methods in them like so:
namespace MyApiControllerClass
{
[Authorize]
[RoutePrefix("users")]
public class UsersApiController : ControllerBase
{
private readonly UserContext _context;
public UsersApiController(UserContext context)
{
_context = context;
}
[Route("/login")]
public IHttpActionResult LoginUser(User user)
{
try
{
// login logic here
return Ok(); // you can return whatever you need
}
catch (Exception exception)
{
// log any issues using your preferred method of logging
return InternalServerError(); // you can return different status codes as well. Depends on what you want
}
}
}
}
You can read more about the Authorize annotation here and customize it to your liking.
Then you fire up your web project which will be available at a local URL that you can set in the project's configuration say http://localhost:4000/ which then makes your controller URL available at http://localhost:34501/users/login. Then you use this URL in your Javascript call and add the User object in the request body.
I have my angular service like:
GetPaymentDeadlineExtension(data: PatientInput): Observable<any> {
return this.httpClient.post<any>(
this.root + `/api/PaymentDeadline/RegisterPatientInput`,data);
}
in my web api controller:
[Route("RegisterPatientInput")]
public SrvInvoiceCompositView[] RegisterGetPaymentDeadlineExtension(PatientInput data)
{
SrvInvoiceCompositView[] list = null;
string ContractNo = String.Empty;
string DktInvoiceNo = String.Empty;
try
{
ContractNo = data.BillNumber.Split('-')[0];
DktInvoiceNo = data.BillNumber.Split('-')[1];
list = DkService.SrvFindInvoiceCompositViewDentaPay(DktInvoiceNo, data.Amount, data.PatientNumber, ContractNo);
}
catch(Exception ex)
{
// exception to be returned to angular app.
}
return list;
}
and in my component.ts file:
this.homePageService.GetPaymentDeadlineExtension(this.input).subscribe(
data=>
{
this.patientInfo = data;
},
error=>
{
//i want to get my ex.message here, so i can display it
}
)
this.homePageService.GetPaymentDeadlineExtension(this.input)
.pipe(catchError((error)=> { handleError here}).subscribe(
data=>
{
this.patientInfo = data;
}
)
More info: https://www.learnrxjs.io/learn-rxjs/operators/error_handling/catch
To get an error in RxJS subscribe method you have to return such a http response that doesn't have 2xx status code. Based on your code snippet Bad Request (400) could be a good choice for example. So on .NET Core side you need to return an IActionResult following way:
[Route("RegisterPatientInput")]
public IActionResult RegisterGetPaymentDeadlineExtension(PatientInput data)
{
SrvInvoiceCompositView[] list = null;
string ContractNo = String.Empty;
string DktInvoiceNo = String.Empty;
try
{
ContractNo = data.BillNumber.Split('-')[0];
DktInvoiceNo = data.BillNumber.Split('-')[1];
list = DkService.SrvFindInvoiceCompositViewDentaPay(DktInvoiceNo, data.Amount, data.PatientNumber, ContractNo);
return Ok(list); // This is has http status code 200 in the http response
}
catch(Exception ex)
{
return BadRequest(ex.Message); // This has http status code 400 in the http response
}
}
If you put in the Angular Component file following:
this.homePageService.GetPaymentDeadlineExtension(this.input).subscribe(
data=>
{
this.patientInfo = data;
},
error=>
{
console.log(error);
}
)
After a http request you will be able to see the exception message from the backend in the browser console.
I don't know exactly the use case of the developed software, but it is not recommended to display the exception on the frontend side in production. A hacker could extract some information from the server code with causing intentionally exceptions.
I have an application that uses JavaScript with Vue.js for the front-end and PHP with Laravel for the back-end.
Right now, when I make a GET request from my front-end to my back-end on URL /getSummoner/{summonerName}, I make another GET request from my back-end to a third party API in order to get the details for a user with a certain summoner name like this:
public function getSummoner($summonerName){
$summoner = Summoner::where('summoner_name', $summonerName)->first();
if ($summoner === null) {
$apiKey = env("RIOT_API_KEY");
$region = env("EUW");
$getSummonerInfo = file_get_contents($region . "/lol/summoner/v4/summoners/by-name/" . $summonerName . "?api_key=" . $apiKey);
$summonerInfo = json_decode($getSummonerInfo);
$summoner = new Summoner();
$summoner->summoner_name = $summonerName;
$summoner->summoner_info = json_encode($summonerInfo);
$summoner->save();
} else {
$summonerInfo = json_decode($summoner->summoner_info);
}
return response()->json([
'summonerInfo' => $summonerInfo,
], 201);
}
And then I return a JSON response to my front-end with the summoner info. This all works fine and dandy as long as a user with that summoner name exists. If he doesn't exists, the GET request fails so the rest of my function fails and in return I get an error on my front-end.
So I am wondering what am I supposed to do to get a 404 page on the front-end if my back-end GET request doesn't go through? Both on the front and back-end. I assume I need to return some sort of response from the back-end and then based on that response do something on the front-end?
Here's my front-end:
<template>
<div>{{ summonerInfo }}</div>
</template>
<script>
import axios from 'axios'
import router from '../router'
export default {
data(){
return {
summoner: this.$route.params.summonerName,
summonerInfo: '',
}
},
methods: {
user(action){
let trimmedSummoner = this.summoner.replace(/\s+/g, '');
axios.get('/' + action + 'Summoner/' + trimmedSummoner)
.then((response) => {
this.summonerInfo = response.data.summonerInfo
})
.catch(function (error) {
console.log(error);
})
}
},
watch:{
$route (to, from){
this.summoner = this.$route.params.summonerName
this.user('get')
}
},
mounted(){
this.user('get')
}
}
</script>
One poor mans way of doing this would be to wrap your request in a try / catch. This way, when you request fails, you have the opportunity to catch it and redirect. Downside to this method is that it doesn't give you any info on what the status code is (4xx vs 5xx, etc...).
However, a proper solution would be to use Http Interceptors to handle this.
How can you use axios interceptors?
Here is another example using try / catch approach:
https://gist.github.com/fgilio/230ccd514e9381fafa51608fcf137253
They've also got quite a few examples on this within their GitHub Docs:
https://github.com/axios/axios
Interceptor Example:
axios.interceptors.response.use((response) => {
if(response.status === 401) {
alert("You are not authorized");
}
return response;
}, (error) => {
if (error.response && error.response.data) {
return Promise.reject(error.response.data);
}
return Promise.reject(error.message);
});
I am implementing authentication where I added a token in response from server side.
I am trying to read this header value returned from server in angularjs however I don't see this header value present. Here is my javascript console.
EDIT:
return base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var response = task.Result;
if (response.RequestMessage.Headers.Contains(TOKEN_NAME))
{
string token = response.RequestMessage.Headers.GetValues(TOKEN_NAME).FirstOrDefault();
response.Headers.Add("Access-Control-Expose-Headers", TOKEN_NAME);
response.Headers.Add(TOKEN_NAME, token);
}
return response;
});
Is the access/authenticate endpoint returning the token as data in the success method or is the token being set in the server side code?
-Update-
If you set the token in HttpContext.Current.Response.AppendHeader('X-Token', "<some token value">); You should be able to grab it in your $http promise
$http.get("<api endpoint>").then(function(data){
$log.log("data.config", data.config);
$log.log("data.headers()", data.headers());
$log.log("X-Token Header", data.headers()['x-token']);
});
data.config is the headers sent to the server such as the accept and any authorization headers.
data.headers() is the function that returns all headers that were set server side.
response.Headers.Add("Access-Control-Expose-Headers", TOKEN_NAME); this line will ensure this header is available to the server
So if I understand correctly your passing x-token in the header of the api request and the Delegating Handler is looking for TOKEN_NAME and then resetting it and then your trying to access it in the promise of $http. I just put together a test for this case and im getting back x-token;
-Sample angular app
(function () {
var app = angular.module('app', []);
app.config(function ($httpProvider) {
$httpProvider.defaults.headers.common["x-token"] = "";
});
app.controller('home', function ($http, $log) {
$http.get('/api/car/get')
.then(function (response) {
$log.log("Response headers",response.headers());
$log.log(response.headers()["x-token"]);
});
});
})();
-Console window
-CustomDelegatingHandler i dont use the variable token because I dont have a token endpoint to get one. Instead I just passed back a random GUID.
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
return await base.SendAsync(request, cancellationToken).ContinueWith(task =>
{
var response = task.Result;
//Are you sure your passing this check by setting the x-token common header in your angular $http requests?
if (response.RequestMessage.Headers.Contains(TOKEN_NAME))
{
string token = response.RequestMessage.Headers.GetValues(TOKEN_NAME).FirstOrDefault();
response.Headers.Add("Access-Control-Expose-Headers", TOKEN_NAME);
response.Headers.Add(TOKEN_NAME, Guid.NewGuid().ToString());
}
return response;
}, cancellationToken);
}