laravel user api_token is undefined - json

i'm getting the 'unauthorized' error when trying to post a new comment with axios ..... i added (console.log(this.user.api_token);) just before axios.post in postComment() method . the output is : "undefined" !!!!!!!!!!
i'm learning and i don't know much about api's . but i don't think user api_token is to be set up manually .or does it ???
the script :
<script>
const app = new Vue({
el: '#app',
data: {
comments: {},
commentBox: '',
post: {!! $post->toJson() !!},
user: {!! Auth::check() ? Auth::user()->toJson() : 'null' !!}
},
mounted() {
this.getComments();
},
methods: {
getComments() {
axios.get('/api/post/'+this.post.id)
.then((response) => {
this.comments = response.data
})
.catch(function (error) {
console.log(error);
});
},
postComment() {
console.log(this.user.api_token);
axios.post('/api/post/'+this.post.id , {
api_token: this.user.api_token,
body: this.commentBox
})
.then((response) => {
this.comments.unshift(response.data);
this.commentBox = '';
})
.catch((error) => {
console.log(error);
})
}
}
})
api route
Route::get('/post/{post}', 'CommentController#index');
Route::middleware('auth:api')->group(function () {
Route::post('/post/{post}', 'CommentController#store');
});
CommentController
public function index(Post $post){
return response()->json($post->comments()->with('user')->get());
}
public function store(Request $req,Post $post){
$comment=$post->comment()->create([
'user_id'=>auth::id(),
'body'=>$req->body
]);
$comment=Comment::where('id',$comment->id)->with('user')->first();
return $comment->toJson;
}

If you are trying to consume your own api from vuejs there's no need to set the api token manually. Just update the web middleware group in app/Http/Kernel.php to include this line:
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class
This middleware will attach a laravel_token cookie that contains an encrypted JWT that Passport will use to authenticate API requests from your JavaScript application.
Read more here: https://laravel.com/docs/5.6/passport#personal-access-tokens
But, if you are consuming this same api from an external source like a mobile app, an api token will be required by passport to authenticate the request. The token can be created when the user is logged in or registered. Here's how:
//create a token
$token = $user->createToken('Token Name')->accessToken;
Then add an headers object to axios when making a request to the api
axios({
method: 'method',
url: 'url',
headers: {
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$token
}
})
.then()
.catch()
Read more here: https://laravel.com/docs/5.6/passport#managing-personal-access-tokens

Related

Unable to fetch data from server due to serialization problem using NextJS?

I'm currently using axios and NextJS.
I currently have this code in my component:
export async function getServerSideProps(context) {
const data = await getVideo(context.query.id);
console.log('data: ', data);
// console.log('context: ', context);
console.log('context params: ', context.params);
console.log('context query: ', context.query);
if (!data) {
return { notFound: true };
}
return {
props: {
videoId: context.params.id,
videoSlug: context.params.slug,
videoContent: data
}
};
}
This getserverSideProps call the function of getVideo which looks exactly like this:
export const getVideo = (id) => async (dispatch) => {
dispatch({ type: CLEAR_VIDEO });
try {
console.log('Action file: ', id);
const res = await api.get(`/videos/${id}`);
return dispatch({
type: GET_VIDEO,
payload: res.data
});
} catch (err) {
dispatch({
type: VIDEO_ERROR,
payload: { msg: err.response?.statusText, status: err.response?.status }
});
}
};
Said function goes through my api function to make requests to backend:
import axios from 'axios';
import { LOGOUT } from '../actions/types';
import { API_URL } from '../config';
const api = axios.create({
baseURL: `${API_URL}/api/v1`,
headers: {
'Content-Type': `application/json`
}
});
/**
intercept any error responses from the api
and check if the token is no longer valid.
ie. Token has expired
logout the user if the token has expired
**/
api.interceptors.response.use(
(res) => {
res;
console.log('Res: ', res.data);
},
(err) => {
if (err?.response?.status === 401) {
typeof window !== 'undefined' &&
window.__NEXT_REDUX_WRAPPER_STORE__.dispatch({ type: LOGOUT });
}
return Promise.reject(err);
}
);
export default api;
It works great when doing POST, PUT,PATCH requests.
As you can see, I'm doing a console.log('data: ',data) but it returns [AsyncFunction (anonymous)] whenever I read the terminal; on the other hand, the front-end returns this error:
Server Error Error: Error serializing .videoContent returned from
getServerSideProps in "/videos/[id]/[slug]". Reason: function
cannot be serialized as JSON. Please only return JSON serializable
data types.
Does anyone knows how to solve this?
NOTE: I'm using react-redux, redux and next-redux-wrapper.
That is because your getVideo function returns another function. The right way to call it would be:
const data = await getVideo(context.query.id)()//<- pass in the dispatch here
But you should not use redux in the backend like that. I think you can completely remove it.
export const getVideo async (id) => {
try {
console.log('Action file: ', id);
const res = await api.get(`/videos/${id}`);
return res.data
});
} catch (err) {
return { msg: err.response?.statusText, status: err.response?.status }
}
};
// call
const data = await getVideo(context.query.id)

I need to fetch API to get a raw value from response same as the result in POSTMAN but fail?

I am new from here. Just stuck on some problem of fetching the data from frontend(react) to the raw value in JSON. For the login part, when I enter the email and password, supposedly the response are same as the result in POSTMAN, but i get the error. I am figure out this issue for almost oneweek. I would be appreciate for those who help me to solve on this issue. I will elaborate further on below about my situation:
Here is the response of API from postman (supposedly I should get this response):
The result I get in the browser:
Source Code:
constructor (props){
super(props);
this.state ={
loginEmail: '',
loginPassword: ''
}
this.login = this.login.bind(this);
this.onChange = this.onChange.bind(this);
}
login(){
PostData('api/users/login', this.state).then ((result) => {
let responseJSON = result;
console.log(responseJSON);
});
}
PostData:
export function PostData(type, userData = {}){
let BaseUrl = "https://ems-unimas-58134.herokuapp.com/"
return new Promise((resolve, reject) => {
fetch(BaseUrl+type,{
method: "POST",
body: JSON.stringify(userData),
Accept: 'application/json',
// headers:{
// 'Content-Type': 'application/json'
// }
}).then(res => res.json())
.then((responseJson) => {
resolve(responseJson);
})
.catch((error)=>{
console.error('Error:', error);
})
});
}
Commend down here if anyone of you need more code.
The problem is you need to allow CORS.
You can read more about CORS in here

how to fetch api(POST) with header in react native app

I am trying to put three params in my post request to particular api but i didn't get the response as i expected. API works fine in my Postman but i am not sure about my fetching method in my react native app i am new to this so i don't know how to put headers in my api request i followed some docs but didn't get much please have a look and answer my question.
constructor (props) {
super (props)
this.state = {
detail: ''
}
}
ComponentDidMount(){
var data = new FormData();
data.append('mobile_number','8615351655')
data.append('mobile_country_code','+21')
data.append('rec_name','Shantanu Talwaar')
}
fetchData = async() => {
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
//this what's exactly look in my postman
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb;
},
body: this.data
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson.detail)
}).catch((error) => {
alert('error')})}
render() {
return (
<View style = {styles.container}>
<Button onPress = {this.fetchData} title = "fetch"/>
<Text style={styles.text}>Fetched data displays below</Text>
<Text style={styles.text}>{this.state.detail}</Text>
</View>
)
}
}
This is the result i am having right now in my alert box: "Authentication credentials were not provided."
There is a ' missing after your token.
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb;
And as it is a JSON Object you should remove the semi-colon
So, the final code will be
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
There is also another problem. The data declaration is not accessible from the fetch function. So you should do something like this.
fetchData = async() => {
var data = new FormData();
data.append('mobile_number','8615351655')
data.append('mobile_country_code','+21')
data.append('rec_name','Shantanu Talwaar')
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
//this what's exactly look in my postman
'Authorization': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
},
body: data
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson.detail)
}).catch((error) => {
alert('error')
})
}
i think you can use "x-access-token" as header name for authentication token and place Content-Type too.
fetchData = () => {
fetch('http://link.com/link/',
{
method: 'POST',
headers:{
'Content-Type': "application/json",
'x-access-token': 'Token 97a74c03004e7d6b0658dfdfde34fd6aa4b14ddb'
},
body: this.data
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson.detail)
}).catch((error) => {
alert('error')})
}

Fetch in react with json always returns an error

For the following created code in react, after I search similar question, I get always an error (seems that the error is return of a promise).
I am using webpack version 3.1.9
In web-pack configuration I did (don't know whether it is necessary):
module.exports = {
...
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": "*"
}
},
...
Here is my code:
var options = {
method: 'get',
mode: 'no-cors',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Origin': '*'
}
};
let _url = 'my url ... web api returns json';
fetch(_url, options)
.then(response =>
response
.json()
.then(data => ({
data: data,
status: response.status
}))
.catch(err =>
/******ERROR: always catch the error *****/
({ error_data: err })
)
)
.then(res => {
console.log(res);
// console.log(res.status, res.data.title)
})
.catch(err => {
console.log(err);
});
The error in the line with the asterisks, as code above
SyntaxError: Unexpected end of input at eval
The code was checked for restful api in C#:
I did in the controller code:
public ActionResult Index()
{
ActionResult x = Json(db.Trainees.ToList(),
JsonRequestBehavior.AllowGet);
//return Content(db.Trainees.ToList().ToString(),
"application/json");
return Json(db.Trainees.ToList(), JsonRequestBehavior.AllowGet);
// return View(db.Trainees.ToList());
}
I assume it is related to fact that json returns a Promise, as described in: json returns promise
I see that json is problematic. When I change response.json() to response.text() there is no error, but I realize that even I send the options with 'no-cors', I see an information message:
Cross-Origin Read Blocking (CORB) blocked cross-origin response ... with MIME type application/json
Seems that the fetch ignore the options with 'no-cors'.
Any clues, why the code encounters an error?!
Thanks.
Problem had been fixed.
In react I did the changes:
var options = {
method: 'GET',
}
...
In C# restfull api controller I did the changes:
Response.AddHeader("Access-Control-Allow-Origin", "*");
return Json(db.Trainees.ToList(), "application/json",
JsonRequestBehavior.AllowGet);

React Native - Second API Call is not returning value

My problem is that my code is returning an undefined value because of my second API Call:
render(){
const result_postid = this.state.data_one.map(function(val) {
return val.postid;
}).join(',');
const result_spaceid = this.state.data_one.map(function(vall) {
return vall.spaceid;
}).join(',');
//These two will receive values.
const result_image = this.state.data_two.map(function(valll) {
return valll.image;
}).join(',');
//This last one somehow will not receive value
}
Here I am fetching two APIs in the same componentDidMount:
componentDidMount(){
//First API Call
fetch(`http://www.exmaple.com/React/data.php`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
data_one: responseJson,
},function() {
});
}).catch((error) => {
console.error(error);
});
// Second API Call
fetch(`http://www.example.com/React/image_data.php`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
data_two: responseJson,
},function() {
});
}).catch((error) => {
console.error(error);
});
}
To confirm that it wasn't just a data response issue, I deleted the first to const (result_postid) and (result_spaceid) and the error was gone (TypeError: undefined is not a function (evaluating 'this.state.data_two.map(function(valll){return valll.image}')). The data showed successfully, but I need all 3 const to return the value. Is there a way to return all values for all 3 const?
The API calls are asynchronous, when you use the values in the render function some of them do not exist until all the calls return. You should have an initial state in the constructor
constructor(props) {
super(props);
this.state = {
data_one: [],
data_two: []
}
}
That way the values are not undefined. When the API returns the value, then the setState will trigger the render again.
Also, why do you have an empty function in the setState in the callbacks?
It should be something like
this.setState({
data_two: responseJson,
});
A couple of recommendations:
Use camelCase for variable naming, _ is not an usual standard in JS
Move the API calls to a different file, that will help you keep the component more organized. Then from componentDidMount you just call the function to make the request.