nuxtjs middleware rest API raw data requests - nuxtjs

I have build nuxtjs example with built in rest API requests with middleware technique. In index.js of my middleware section I put some code :
export default {
handler(req, res) {
res.write('Everything ok!')
console.log(req);
console.log(res);
res.end()
},
path: '/test15'
}
When I call http://ip:port/test15/?cmd=somecmd&param=testparam
In console.log I get params data in log, everything nice. No matter which method used, post or get, it also fixed in log.
The problem is when I try to send raw data (ex json) in request body or form data. I can`t see them in any log output.
So question is, is it possible to send some data in such requests via middleware ?
Thanks!

middleware in nuxt is a sandwich for internal routes aka client side. For your question serverMiddleware is the answer that work on the server side. You can checkout more here
Quick example:
In your nuxt.config.js file add like below
serverMiddleware: [
{ path: '/api/subscribe', handler: '~/api/subscribe' }
],
Then create an api folder you can create subscribe.js file to add relative api route.
import express from 'express'
const app = express()
app.get('/subscribe', async (req, res) => {
res.send('love to the world');
})
export default {
path: '/api',
handler: app
}

Related

Laravel passport 404, Trying to connect a front end client to Laravel back-end api

Please help explain me a bit. I'm very new to this back-end, OAuth 2.0. I'm trying to make my Laravel project to become an api with Passport authorization system. But after following the passport installation guide from official documents and watching youtube tutorials, I still can't connect Laravel to my front end. Can you please point out what I'm missing ? Sorry if this question is super vague, I don't really understand much what's going on.
How and where do I create a new client for my passport back end api ? Should this code be in my front end (or in laravel?) ?
const data = {
name: 'Client Name',
redirect: 'http://example.com/callback'
};
axios.post('/oauth/clients', data)
.then(response => {
console.log(response.data);
})
.catch (response => {
// List errors on response...
});
In the official documents which talks about issuing access tokens with JSON api, there's this explanation.
However, you will need to pair Passport's JSON API with your own frontend to provide a dashboard for your users to manage their clients. Below, we'll review all of the API endpoints for managing clients. For convenience, we'll use Axios to demonstrate making HTTP requests to the endpoints.
The JSON API is guarded by the web and auth middleware; therefore, it may only be called from your own application. It is not able to be called from an external source.
It didn't explain how I could pair my frontend to this Laravel app. I tried adding this to my front end javascript.
const BASE_URL = 'http://127.0.0.1:8000/api';
**
* Trying Passport JSON api to get all clients for a given user.
*/
const getClients = async () => {
try {
const response = await axios.get(`${BASE_URL}/oauth/clients`);
const clients = response.data;
console.log('Here are your clients', clients);
} catch (errors) {
console.error(errors);
}
}
/**
* Trying to create a new client. Not sure if this is equivalent to linking this external app to the backend api or not
*/
const addClient = async() => {
const data = {
name: 'front end jajaja',
redirect: 'http://www.google.com'
};
const response = await axios.post(`${BASE_URL}/oauth/clients`, data);
console.log(response.data);
}
/**
* main function to test it all
*/
const main = () => {
addClient();
// getClients();
}
main();
but after I ran npm run dev and the main() method is called from the front end, console displayed an error saying
POST http://127.0.0.1:8000/api/oauth/clients 404 (Not Found)
I haven't edit routes/api.php.
<?php
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
And from a tutorial by Andrew, he said he used Laravel breeze to make a mock client, but can I use my super simple front end JavaScript instead ? Can you please explain me, how can I connect my front to the back ? How can I get the authorization code, client secret ??

How do I send CSRFToken in my axios requests using Nuxt and Django on the backend?

I'm using Django Rest as a backend api, and each API call requires a CSRF Token in the headers. In my "Applications" tab in Developer Tools, I clearly have a "csrftoken" value and I somehow need to extract that with each subsequent POST request that my Nuxt application does (using Nuxt/Axios)
My settings.py looks like this:
CORS_ORIGIN_WHITELIST = (
"http://localhost:3000",
"http://127.0.0.1:3000",
)
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000",
]
CORS_EXPOSE_HEADERS = ['Content-Type', 'X-CSRFToken']
CORS_ALLOW_CREDENTIALS = True
CSRF_COOKIE_SAMESITE = "Lax"
SESSION_COOKIE_SAMESITE = "Lax"
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_HTTPONLY = True
I have tried using js-cookies with Cookies.get("csrftoken") which just returns undefined. Is the cookie not accessible because it's set to HTTPONLY`?
What is the recommended step here? Should I create a view in my django backend to generate a CSRF Token, and then before making each request on the frontend, I call this view in my Django app to fetch the token?
E.g
def get_csrf(request):
response = JsonResponse({"detail": "CSRF cookie set"})
response["X-CSRFToken"] = get_token(request)
return response
Not sure how to proceed..
My Nuxt/Axios requests looks something like this:
const response =
await this.$axios.$post("/api/portfolios/", stockData,
{ headers: { "X-CSRFToken": /* Need some value here. */ }
});
I can however get the cookie using nuxtServerInit in my Nuxt Store:
async nuxtServerInit({commit}) {
console.log(this.$cookies.get("csrftoken")) // this works, can store it in some state
},
I can store the value from nuxtServerInit in a Nuxt store. However, whenever I logout, how do I make sure to extract the new csrftoken from the browser? The nuxtServerInit part above only works if I do a page reload, which isn't ideal.
Appreciate any guidance I can get.
Setup axios with default xsrfHeaderName and xsrfCookieName values via nuxt plugin.
When configured, axios will include in request your csrf header with cookie value if it's present in cookies.
in nuxt.config.js include your new plugin
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
'~/plugins/axios',
]
create plugins/axios.js
There is the option to declare as global default config, or for a nuxt instance.
// content of plugins/axios.js
/*
// This is a global config declaration that works on any axios instance,
// meaning that if you just import axios from 'axios' in any place, you will get those.
// This will also work on the axios instance that nuxt creates and injects.
import axios from 'axios'
axios.defaults.xsrfHeaderName = 'x-csrftoken'
axios.defaults.xsrfCookieName = 'csrftoken'
*/
export default function ({ $axios }) {
// This is a nuxt specific instance config, this will work in
// everyplace where nuxt inject axios, like Vue components, and store
$axios.defaults.xsrfHeaderName = 'x-csrftoken'
$axios.defaults.xsrfCookieName = 'csrftoken'
}

How to get http response from lumen API asynchronously

Lumen is sending response to the client side according to the order of requests. It is holding next response until previous response completes. I need to make it asynchronously
Laravel Lumen Routing Code:
$router->get('waist-xxxxxxx/v20/', ['uses' => 'DemoController#fnDemoFunction']);
$router->get('waist-xxxxxxx/v20/{serverSideRowUuid}', ['uses' => 'DemoController#fnDemoFunction']);
$router->post('waist-xxxxxxx/v20/', ['uses' => 'DemoController#create']);
$router->put('waist-xxxxxxx/v20/{serverSideRowUuid}', ['uses' => 'DemoController#update']);
$router->options('waist-xxxxxxx/v20', function () {
return response('OK', \Illuminate\Http\Response::HTTP_NO_CONTENT)
->header('Access-Control-Allow-Credentials', 'true')
->header('Connection', 'keep-alive');
});
$router->options('waist-xxxxxxx/v20/{serverSideRowUuid}', function () {
return response('OK', \Illuminate\Http\Response::HTTP_NO_CONTENT)
->header('Access-Control-Allow-Credentials', 'true')
->header('Connection', 'keep-alive');
});
Vue.js App code for API calling:
export default {
methods: {
async mxGetDataFromDb() {
/*
TODO: Need to restrict the load to current data
api is vuex-orm-axios plugin function
When using json-server backend the code is:
*/
console.log('reminders req sent')
const proRemsFromDB = await clientSideTable.api().get(clientSideTable.apiUrl)
console.log('reminders recd')
if (proRemsFromDB.ok) {
}
},
},
}
Here is a screenshot for better understanding: enter image description here
I suspect you're using php artisan serve to test with.
This command utilizes the built-in PHP development server. It's a great tool, but it can only handle one request at a time:
The web server runs only one single-threaded process, so PHP applications will stall if a request is blocked.
In general, while php artisan serve is great for quick testing, you'll want to set up something like Laravel Homestead or some other more robust development environment long-term.

Nuxt Apollo with dynamic headers for a session based authentication

Apollo is not storing the header from the query dynamically.
pages/index.vue
methods: {
fetchCars() {
const token = Cookies.get('XSRF-TOKEN')
console.log(token) // 🟢 Token is shown in console
this.$apollo.query({
query: gql`
query {
cars {
uuid
name
}
}
`,
headers: {
'X-XSRF-TOKEN': token, // â­• Fetch without header
},
})
},
},
Is there a way to set the header value new for every Apollo request?
I have a separate Frontend and Backend. For the Frontend I am using Nuxt.js with Apollo. I want to have a session based communication with my server. For this reason I need to send the CSRF-Token with every Request.
Now the problem: On the first load of the page there is no Cookie set on the browser. I do a GET-Request on every initialization of my Nuxt application.
plugins/csrf.js
fetch('http://127.0.0.1:8000/api/csrf-cookie', {
credentials: 'include',
})
Now I have a valid Cookie set on my side and want to communicate with the GraphQL Server but my header is not set dynamically in the query. Does anyone know how I can solve this?
My Laravel Backend is throwing now a 419 Token Mismatch Exception because I did not send a CSRF-Token with my request.
Link to the repository: https://github.com/SuddenlyRust/session-based-auth
[SOLVED] Working solution: https://github.com/SuddenlyRust/session-based-auth/commit/de8fb9c18b00e58655f154f8d0c95a677d9b685b Thanks to the help of kofh in the Nuxt Apollo discord channel 🎉
In order to accomplish this, we need to access the code that gets run every time a fetch happens. This code lives inside your Apollo client's HttpLink. While the #nuxtjs/apollo module gives us many options, we can't quite configure this at such a high level.
Step 1: Creating a client plugin
As noted in the setup section of the Apollo module's docs, we can supply a path to a plugin that will define a clientConfig:
// nuxt.config.js
{
apollo: {
clientConfigs: {
default: '~/plugins/apollo-client.js'
}
}
}
This plugin should export a function which receives the nuxt context. It should return the configuration to be passed to the vue-cli-plugin-apollo's createApolloClient utility. You don't need to worry about that file, but it is how #nuxtjs/apollo creates the client internally.
Step 2: Creating the custom httpLink
In createApolloClient's options, we see we can disable defaultHttpLink and instead supply our own link. link needs to be the output of Apollo's official createHttpLink utility, docs for which can be found here. The option we're most interested in is the fetch option which as the docs state, is
a fetch compatible API for making a request
This boils down to meaning a function that takes uri and options parameters and returns a Promise that represents the network interaction.
Step 3: Creating the custom fetch method
As stated above, we need a function that takes uri and options and returns a promise. This function will be a simple passthrough to the standard fetch method (you may need to add isomorphic-fetch to your dependencies and import it here depending on your setup).
We'll extract your cookie the same as you did in your question, and then set it as a header. The fetch function should look like this:
(uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
Putting it all together
Ultimately, your ~/plugins/apollo-client.js file should look something like this:
import { createHttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-fetch'
export default function(context) {
return {
defaultHttpLink: false,
link: createHttpLink({
uri: '/graphql',
credentials: 'include',
fetch: (uri, options) => {
const token = Cookies.get('XSRF-TOKEN')
options.headers['X-XSRF-TOKEN'] = token
return fetch(uri, options)
}
})
}
}

Vue Router and Vuex

I have 2 questions.
1. How can I catch undefined routes and redirect to 404 page?
2. How I can use Vuex actions to get data from api? I know that vuex mutations must be sync and actions async. But I can get data with mutations and can use then promise. but can't in actions or I do anything mistake. Please give me beautiful example for that(component type). I use vuex in laravel mix in Laravel project. Thanks...
Generally speaking, you shouldn't be getting undefined routes if you're defining all of the routes within an app. You can define a redirect in your routes configuration as such:
[
{
path: 'admin/posts/list',
name: 'post-list',
},
{
path: 'admin/posts',
redirect: 'admin/posts/list'
}
]
// you can also redirect to a named route instead
// of a path like this:
{
path: 'admin/posts',
redirect: { name: 'post-list' }
}
If you wanted to do a "catch all" that grabs any paths not matched and redirect to your 404 component/view, then you could do it like this:
{
path: '*',
redirect: '/404'
}
Make sure that is at the bottom of your routes definition as the last route because it will catch any routes in the tree it is above.
As for your question about mutations/actions, asynchronous API requests like fetching data from an API only every happen within actions when you're using Vuex.Taken from the documentation on actions:
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}

Resources