How to Make http Request to My Project API from Firebase Cloud function? - firebase

Hello I am trying to make an API Post request using Firebase cloud function,Here are the code.
My effort is to get details from cloud and make an http request to my project's API. But i am getting an error of can not find module!!i have already put it.
so how to make an api call??
Here is my index.ts
import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import {TenantServiceProxy, CreateTenantInput} from '../../src/app/cloud/cloud-service';
let _tenantService: TenantServiceProxy;
const tenant = new CreateTenantInput();
admin.initializeApp();
export const onOrganizationUpdate =
functions.firestore.document('organizations/{id}').onUpdate(change => {
const after = change.after.data()
const payload = {
data: {
OrganizationId: String(after.OrganizationId),
Name: String(after.Name),
IsDeleted: String(after.IsDeleted)
}
}
console.log("updated", payload);
https.get('https://reqres.in/api/users?page=2', (resp: any) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk: any) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log("-------------------->",JSON.parse(data));
});
}).on("error", (err: any) => {
console.log("Error: " + err.message);
});
return admin.messaging().sendToTopic("OrganizationId", payload)
})
export const onOrganizationCreate =
functions.firestore.document('organizations/{id}').onCreate(change=>{
const onCreationTime =change.data()
const payload={
data:{
organizationId:String(onCreationTime.organizationId),
name:String(onCreationTime.name),
isDeleted:String(onCreationTime.isDeleted)
},
}
console.log("created",payload);
tenant.pkOrganization = payload.data.organizationId;
tenant.name = payload.data.name;
tenant.isDeleted = Boolean(payload.data.isDeleted);
_tenantService.createTenant(tenant).subscribe(()=>{
console.log("created",payload);
});
return admin.messaging().sendToTopic("OrganizationId",payload)
})
Here is the cloud.service.module.TS
//cloud service module
import { AbpHttpInterceptor } from '#abp/abpHttpInterceptor';
import { HTTP_INTERCEPTORS } from '#angular/common/http';
import { NgModule } from '#angular/core';
import * as ApiServiceProxies from '../../app/cloud/cloud-service';
#NgModule({
providers: [
ApiServiceProxies.TenantServiceProxy,
{ provide: HTTP_INTERCEPTORS, useClass: AbpHttpInterceptor, multi: true }
]
})
export class CloudServiceModule { }
Here is My api call service
#Injectable()
export class TenantServiceProxy {
private http: HttpClient;
private baseUrl: string;
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
constructor(#Inject(HttpClient) http: HttpClient, #Optional() #Inject(API_BASE_URL) baseUrl?: string) {
this.http = http;
this.baseUrl = baseUrl ? baseUrl : '';
}
createTenant(input: CreateTenantInput | null | undefined): Observable<void> {
let url_ = this.baseUrl + '/api/services/app/Tenant/CreateTenant';
url_ = url_.replace(/[?&]$/, '');
const content_ = JSON.stringify(input);
const options_: any = {
body: content_,
observe: 'response',
responseType: 'blob',
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
return this.http.request('post', url_, options_).pipe(_observableMergeMap((response_: any) => {
return this.processCreateTenant(response_);
})).pipe(_observableCatch((response_: any) => {
if (response_ instanceof HttpResponseBase) {
try {
return this.processCreateTenant(<any>response_);
} catch (e) {
return <Observable<void>><any>_observableThrow(e);
}
} else {
return <Observable<void>><any>_observableThrow(response_);
}
}));
}
protected processCreateTenant(response: HttpResponseBase): Observable<void> {
const status = response.status;
const responseBlob =
response instanceof HttpResponse ? response.body :
(<any>response).error instanceof Blob ? (<any>response).error : undefined;
const _headers: any = {}; if (response.headers) { for (const key of response.headers.keys()) { _headers[key] = response.headers.get(key); } }
if (status === 200) {
return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
return _observableOf<void>(<any>null);
}));
} else if (status !== 200 && status !== 204) {
return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
return throwException('An unexpected server error occurred.', status, _responseText, _headers);
}));
}
return _observableOf<void>(<any>null);
}
}
I have defined the module in my services.

Related

Graphql subscriptions not working on serverless environment

I'm using graphql yoga and apollo client in my next app. Graphql yoga suggests this example for apollo client. link It works fine on non-serverless environment but when I deploy on vercel, subscriptions not working. I have tried checking for if it's running on browser but didn't do much. Here's my current apollo client
import {
ApolloLink,
Observable,
ApolloClient,
InMemoryCache,
} from '#apollo/client/core'
import { split } from '#apollo/client/link/core'
import { HttpLink } from '#apollo/client/link/http'
import { print, getOperationAST } from 'graphql'
import { setContext } from '#apollo/client/link/context'
import { getCookie } from 'cookies-next'
const isBrowser = typeof window !== 'undefined'
const token = getCookie('token')
class SSELink extends ApolloLink {
constructor() {
super()
}
request(operation) {
const url = new URL(`${process.env.NEXT_PUBLIC_APP_BASE_URL}/api/graphql`)
url.searchParams.append('query', print(operation.query))
if (operation.operationName) {
url.searchParams.append(
'operationName',
JSON.stringify(operation.operationName)
)
}
if (operation.variables) {
url.searchParams.append('variables', JSON.stringify(operation.variables))
}
if (operation.extensions) {
url.searchParams.append(
'extensions',
JSON.stringify(operation.extensions)
)
}
return new Observable((sink) => {
const eventsource = new EventSource(url.toString(), this.options)
eventsource.onmessage = function (event) {
const data = JSON.parse(event.data)
sink.next(data)
if (eventsource.readyState === 2) {
sink.complete()
}
}
eventsource.onerror = function (error) {
sink.error(error)
}
return () => eventsource.close()
})
}
}
const uri = `${process.env.NEXT_PUBLIC_APP_BASE_URL}/api/graphql`
const sseLink = isBrowser ? new SSELink({ uri }) : null
const httpLink = new HttpLink({ uri })
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
...(isBrowser && token && { authorization: `Bearer ${token}` }),
},
}
})
const link = isBrowser
? split(
({ query, operationName }) => {
const definition = getOperationAST(query, operationName)
return (
definition?.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
sseLink,
httpLink
)
: authLink.concat(httpLink)
export default new ApolloClient({
ssrMode: !isBrowser,
link,
cache: new InMemoryCache(),
})

Set-Cookie header from NestJS server not accepted by fetchBaseQuery when using Next.js SSR

I'm trying to do authorization using JWT access&refresh tokens (Next.js SSR + Redux Toolkit RTK Query + NestJS). When I receive a response from the server on the client (for example using Postman) the cookies sent by the server are saved. But when I do it on SSR using RTK Query Set-Cookie from the server just doesn't do anything. Sorry if I misunderstood something, I'm new to this.
NSETJS auth.controller.ts:
import {
Controller,
Get,
HttpCode,
HttpStatus,
Post,
Req,
Res,
UseGuards
} from '#nestjs/common';
import { Response } from 'express';
import { ApiTags } from '#nestjs/swagger';
import { Request } from 'express';
import { AuthService } from './auth.service';
import { DiscordAuthGuard } from './guards/discord-auth.guard';
import JwtAuthGuard from './guards/jwt-auth.guard';
import { RequestWithUser } from './auth.interface';
import JwtRefreshGuard from './guards/jwt-auth-refresh.guard';
import { UserService } from '#/modules/user/user.service';
#Controller('auth')
#ApiTags('Auth routes')
export class AuthController {
constructor(
private readonly authService: AuthService,
private readonly userService: UserService
) {}
#Get('login')
#HttpCode(HttpStatus.OK)
#UseGuards(DiscordAuthGuard)
login(#Req() _req: Request) {}
#Get('redirect')
#HttpCode(HttpStatus.OK)
#UseGuards(DiscordAuthGuard)
async redirect(#Req() req: RequestWithUser, #Res() res: Response) {
const { user } = req;
const accessTokenCookie = this.authService.getCookieWithJwtAccessToken(
user.id
);
const refreshTokenCookie = this.authService.getCookieWithJwtRefreshToken(
user.id
);
await this.userService.setCurrentRefreshToken(
refreshTokenCookie.token,
user.id
);
req.res.setHeader('Set-Cookie', [
accessTokenCookie.cookie,
refreshTokenCookie.cookie
]);
return res.redirect('http://localhost:3000');
}
#Get('refresh')
#HttpCode(HttpStatus.OK)
#UseGuards(JwtRefreshGuard)
async refresh(#Req() req: RequestWithUser) {
const { user } = req;
const accessTokenCookie = this.authService.getCookieWithJwtAccessToken(
user.id
);
req.res.setHeader('Set-Cookie', [accessTokenCookie.cookie]);
return user;
}
#Get('me')
#HttpCode(HttpStatus.OK)
#UseGuards(JwtAuthGuard)
me(#Req() req: RequestWithUser) {
const { user } = req;
return user;
}
#Post('logout')
#HttpCode(HttpStatus.OK)
#UseGuards(JwtAuthGuard)
async logout(#Req() req: RequestWithUser) {
const { user } = req;
await this.userService.removeRefreshToken(user.id);
req.res.setHeader('Set-Cookie', this.authService.getCookiesForLogOut());
}
}
NEXT.JS _app.tsx:
import '#/styles/globals.scss';
import { AppProps } from 'next/app';
import { wrapper } from '#/store';
import { me } from '#/store/auth/auth.api';
import { setCredentials } from '#/store/auth/auth.slice';
function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
App.getInitialProps = wrapper.getInitialAppProps(
(store) =>
async ({ ctx, Component }) => {
try {
const { data: user } = await store.dispatch(me.initiate());
if (user !== undefined) {
store.dispatch(
setCredentials({
user,
})
);
}
} catch (err) {
console.log(err);
}
return {
pageProps: {
...(Component.getInitialProps
? await Component.getInitialProps({ ...ctx, store })
: {}),
},
};
}
);
export default wrapper.withRedux(App);
NEXT.JS auth.api.ts:
import { parseCookies } from 'nookies';
import {
BaseQueryFn,
createApi,
fetchBaseQuery,
} from '#reduxjs/toolkit/query/react';
import { HYDRATE } from 'next-redux-wrapper';
import { Mutex } from 'async-mutex';
import { NextPageContext } from 'next/types';
import { IUser } from './auth.interface';
import { destroyCredentials } from './auth.slice';
const mutex = new Mutex();
const baseQuery = fetchBaseQuery({
baseUrl: 'http://localhost:7777/api/auth',
prepareHeaders: (headers, { extra }) => {
const ctx = extra as Pick<NextPageContext<any>, 'req'>;
const windowAvailable = () =>
!!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
if (windowAvailable()) {
console.log('running on browser, skipping header manipulation');
return headers;
}
const cookies = parseCookies(ctx);
// Build a cookie string from object
const cookieValue = Object.entries(cookies)
// .filter(([k]) => k === 'JSESSIONID') // only include relevant cookies
.map(([k, v]) => `${k}=${v}`) // rfc6265
.join('; ');
console.log('figured out cookie value: ' + cookieValue);
headers.set('Cookie', cookieValue);
return headers;
},
credentials: 'include',
});
const baseQueryWithReauth: BaseQueryFn = async (args, api, extraOptions) => {
await mutex.waitForUnlock();
console.log('🔥🔥🔥 sending request to server');
let result = await baseQuery(args, api, extraOptions);
if (result?.error?.status === 401) {
if (!mutex.isLocked()) {
console.log('🔥🔥🔥 401, sending refresh token');
const release = await mutex.acquire();
try {
const refreshResult = await baseQuery('refresh', api, extraOptions);
const setCookies =
refreshResult.meta?.response?.headers.get('set-cookie');
console.log('🔥🔥🔥 response set-cookies:', setCookies);
console.log(
'🔥🔥🔥 refresh response status:',
refreshResult.meta?.response?.status
);
if (refreshResult.data) {
const windowAvailable = () =>
!!(
typeof window !== 'undefined' &&
window.document &&
window.document.createElement
);
if (!windowAvailable()) {
console.log('🔥🔥🔥 running on server');
}
result = await baseQuery(args, api, extraOptions);
console.log(
'🔥🔥🔥 request response status after /refresh',
result.meta?.response?.status
);
} else {
api.dispatch(destroyCredentials());
}
} finally {
release();
}
}
}
return result;
};
export const authApi = createApi({
reducerPath: 'api/auth',
baseQuery: baseQueryWithReauth,
extractRehydrationInfo(action, { reducerPath }) {
if (action.type === HYDRATE) {
return action.payload[reducerPath];
}
},
tagTypes: ['Auth'],
endpoints: (build) => ({
me: build.query<IUser, void>({
query: () => ({
url: '/me',
method: 'GET',
}),
providesTags: ['Auth'],
}),
logout: build.mutation<void, void>({
query: () => ({
url: '/logout',
method: 'POST',
}),
invalidatesTags: ['Auth'],
}),
}),
});
// Export hooks for usage in functional components
export const {
useMeQuery,
useLogoutMutation,
util: { getRunningOperationPromises },
} = authApi;
// export endpoints for use in SSR
export const { me, logout } = authApi.endpoints;
NEXT.JS auth.slice.ts
import { createSlice, PayloadAction } from '#reduxjs/toolkit';
import { HYDRATE } from 'next-redux-wrapper';
import { RootState } from '..';
import { IUser } from './auth.interface';
export interface IAuthState {
user: IUser | null;
}
const initialState: IAuthState = {
user: null,
};
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setCredentials: (
state,
action: PayloadAction<{
user: IUser | null;
}>
) => {
const { user } = action.payload;
state.user = user;
},
destroyCredentials: (state) => {
state.user = null;
},
},
extraReducers: {
[HYDRATE]: (state, action) => {
return {
...state,
...action.payload.auth,
};
},
},
});
export const { setCredentials, destroyCredentials } = authSlice.actions;
export const selectCurrentUser = (state: RootState) => state.auth.user;
export default authSlice.reducer;
NEXT.JS store/index.ts:
import {
configureStore,
ImmutableStateInvariantMiddlewareOptions,
SerializableStateInvariantMiddlewareOptions,
ThunkAction,
} from '#reduxjs/toolkit';
import { Action, combineReducers } from 'redux';
import { Context, createWrapper } from 'next-redux-wrapper';
import botApi from './bots/bot.api';
import authReducer from './auth/auth.slice';
import { authApi } from './auth/auth.api';
// ThunkOptions not exported in getDefaultMiddleware, so we have a copy here
interface MyThunkOptions<E> {
extraArgument: E;
}
// GetDefaultMiddlewareOptions in getDefaultMiddleware does not allow
// providing type for ThunkOptions, so here is our custom version
// https://redux-toolkit.js.org/api/getDefaultMiddleware#api-reference
interface MyDefaultMiddlewareOptions {
thunk?: boolean | MyThunkOptions<Context>;
immutableCheck?: boolean | ImmutableStateInvariantMiddlewareOptions;
serializableCheck?: boolean | SerializableStateInvariantMiddlewareOptions;
}
const rootReducer = combineReducers({
// Add the generated reducer as a specific top-level slice
[botApi.reducerPath]: botApi.reducer,
[authApi.reducerPath]: authApi.reducer,
auth: authReducer,
});
const makeStore = (wtf: any) => {
const ctx = wtf.ctx as Context;
return configureStore({
reducer: rootReducer,
// Adding the api middleware enables caching, invalidation, polling,
// and other useful features of `rtk-query`.
middleware: (gDM) =>
gDM<MyDefaultMiddlewareOptions>({
thunk: {
// https://github.com/reduxjs/redux-toolkit/issues/2228#issuecomment-1095409011
extraArgument: ctx,
},
}).concat(botApi.middleware, authApi.middleware),
devTools: process.env.NODE_ENV !== 'production',
});
};
export type RootState = ReturnType<AppStore['getState']>;
export type AppStore = ReturnType<typeof makeStore>;
export type AppDispatch = ReturnType<typeof makeStore>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action
>;
export const wrapper = createWrapper<AppStore>(makeStore);
I would be grateful to everyone for any help with a solution 🙂.

How can I abstract fetch in sveltkit for ssr?

I'm trying to pass in fetch which apparently isn't defined in my api libraries when using ssr:
<script context="module">
import setup from '$api/create-api';
import Jobs from '$api/jobs';
export async function load({ fetch }) {
setup(fetch);
const jobs = await Jobs.getAll();
return {
props: { jobs }
};
}
</script>
create-api.js
import { browser } from '$app/env';
let fetch = fetch || null;
async function api(path, body = {}, opts = {}) {
path = import.meta.env.VITE_API_ENDPOINT + path;
body = JSON.stringify(body);
const method = opts.method || 'GET';
const headers = {};
if (browser) {
const token = localStorage.getItem('token');
headers.Authorization = token ? 'Bearer ' + token : '';
}
const res = await fetch(path, {
method: opts.method || 'GET',
body: method === 'GET' ? null : body,
headers
});
if (res.ok) {
return await (opts.raw ? res.text() : res.json());
}
throw res;
}
export default api;
export const setup = (f) => {
fetch = f;
};
jobs.js
import api from './create-api';
class Jobs {
static async getAll() {
return await api('/jobs');
}
static async getAllMine() {
return await api('/jobs/me');
}
static async create(job) {
return await api('/jobs', job, { method: 'POST' });
}
static async update(job) {
return await api('/jobs/' + job.id, job, { method: 'PUT' });
}
static async deleteById(id) {
return await api('/jobs/' + id, {}, { method: 'DELETE' });
}
static async getById(id) {
console.log(id);
return await api('/jobs/' + id, {}, { method: 'GET' });
}
}
export default Jobs;
It seems you have to use the fetch passed into the script module for some reason. I tried installing node-fetch but got a ton of errors.

Axios onUploadProgress not called on Nuxtjs project when nuxt#pwa and nuxt#firebase modules installed

A noticed that onUploadProgress from axios are not being called at all on my Nuxt.js Project. After some debugging I found out it is related to the "#nuxtjs/pwa" and "#nuxtjs/firebase" modules. I use firebase auth, and the PWA module uses a service worker to take care of SSR auth and inject the auth token on outgoing requests.
This modules are interfering somehow on the axios onUploadProgress. I use axios to upload files to other Apis.
Once I remove the "#nuxtjs/pwa" module the onUploadProgress from axios gets called normally.
Does anyone have an idea how to fix that?
The versions of the modules:
"#nuxtjs/axios": "^5.13.6",
"#nuxtjs/firebase": "^7.6.1",
"#nuxtjs/pwa": "^3.3.5",
nuxt.config.js
firebase: {
....
services: {
auth: {
ssr: true,
persistence: 'local',
initialize: {
onAuthStateChangedAction: 'auth/onAuthStateChangedAction',
subscribeManually: false,
},
},
firestore: true,
functions: true,
},
}
pwa: {
meta: false,
icon: false,
workbox: {
importScripts: ['/firebase-auth-sw.js'],
dev: process.env.NODE_ENV === 'development',
},
},
Axios upload
const asset = await $axios.post(uploadUrl, formData, {
headers: { 'Content-Type': 'multipart/form-data' },
onUploadProgress: (progressEvent) => {
console.log('onUploadProgress');
const prog = parseInt(
Math.round((progressEvent.loaded / progressEvent.total) * 100)
);
progress(prog);
},
});
the console.log isn't called at all.
firebase-auth-sw
const ignorePaths = ["\u002F__webpack_hmr","\u002F_loading","\u002F_nuxt\u002F"]
importScripts(
'https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js'
)
importScripts(
'https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js'
)
firebase.initializeApp({"apiKey":"AIzaSyDUjfwaCRNG72CaPznknOfbNLySkFQvfrs","authDomain":"j-a-developer-web-site.firebaseapp.com","projectId":"j-a-developer-web-site","storageBucket":"j-a-developer-web-site.appspot.com","messagingSenderId":"393360816421","appId":"1:393360816421:web:75c43cac27032d924502cc"})
// Initialize authService
const authService = firebase.auth()
/**
* Returns a promise that resolves with an ID token if available.
* #return {!Promise<?string>} The promise that resolves with an ID token if
* available. Otherwise, the promise resolves with null.
*/
const getIdToken = () => {
return new Promise((resolve) => {
const unsubscribe = authService.onAuthStateChanged((user) => {
unsubscribe()
if (user) {
// force token refresh as it might be used to sign in server side
user.getIdToken(true).then((idToken) => {
resolve(idToken)
}, () => {
resolve(null)
})
} else {
resolve(null)
}
})
})
}
const fetchWithAuthorization = async (original, idToken) => {
// Clone headers as request headers are immutable.
const headers = new Headers()
for (let entry of original.headers.entries()) {
headers.append(entry[0], entry[1])
}
// Add ID token to header.
headers.append('Authorization', 'Bearer ' + idToken)
// Create authorized request
const { url, ...props } = original.clone()
const authorized = new Request(url, {
...props,
mode: 'same-origin',
redirect: 'manual',
headers
})
return fetch(authorized)
}
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url)
const expectsHTML = event.request.headers.get('accept').includes('text/html')
const isSameOrigin = self.location.origin === url.origin
const isHttps = (self.location.protocol === 'https:' || self.location.hostname === 'localhost' || self.location.hostname === '127.0.0.1')
const isIgnored = ignorePaths.some(path => {
if (typeof path === 'string') {
return url.pathname.startsWith(path)
}
return path.test(url.pathname.slice(1))
})
// https://github.com/nuxt-community/firebase-module/issues/465
if (!expectsHTML || !isSameOrigin || !isHttps || isIgnored) {
event.respondWith(fetch(event.request))
return
}
// Fetch the resource after checking for the ID token.
// This can also be integrated with existing logic to serve cached files
// in offline mode.
event.respondWith(
getIdToken().then(
idToken => idToken
// if the token was retrieved we attempt an authorized fetch
// if anything goes wrong we fall back to the original request
? fetchWithAuthorization(event.request, idToken).catch(() => fetch(event.request))
// otherwise we return a fetch of the original request directly
: fetch(event.request)
)
)
})
// In service worker script.
self.addEventListener('activate', event => {
event.waitUntil(clients.claim())
})
sw
const options = {"workboxURL":"https://cdn.jsdelivr.net/npm/workbox-cdn#5.1.4/workbox/workbox-sw.js","importScripts":["/firebase-auth-sw.js"],"config":{"debug":true},"cacheOptions":{"cacheId":"J.A-Developer-Web-Site-dev","directoryIndex":"/","revision":"qIA7lTEhJ6Mk"},"clientsClaim":true,"skipWaiting":true,"cleanupOutdatedCaches":true,"offlineAnalytics":false,"preCaching":[{"revision":"qIA7lTEhJ6Mk","url":"/?standalone=true"}],"runtimeCaching":[{"urlPattern":"/_nuxt/","handler":"NetworkFirst","method":"GET","strategyPlugins":[]},{"urlPattern":"/","handler":"NetworkFirst","method":"GET","strategyPlugins":[]}],"offlinePage":null,"pagesURLPattern":"/","offlineStrategy":"NetworkFirst"}
importScripts(...[options.workboxURL, ...options.importScripts])
initWorkbox(workbox, options)
workboxExtensions(workbox, options)
precacheAssets(workbox, options)
cachingExtensions(workbox, options)
runtimeCaching(workbox, options)
offlinePage(workbox, options)
routingExtensions(workbox, options)
function getProp(obj, prop) {
return prop.split('.').reduce((p, c) => p[c], obj)
}
function initWorkbox(workbox, options) {
if (options.config) {
// Set workbox config
workbox.setConfig(options.config)
}
if (options.cacheNames) {
// Set workbox cache names
workbox.core.setCacheNameDetails(options.cacheNames)
}
if (options.clientsClaim) {
// Start controlling any existing clients as soon as it activates
workbox.core.clientsClaim()
}
if (options.skipWaiting) {
workbox.core.skipWaiting()
}
if (options.cleanupOutdatedCaches) {
workbox.precaching.cleanupOutdatedCaches()
}
if (options.offlineAnalytics) {
// Enable offline Google Analytics tracking
workbox.googleAnalytics.initialize()
}
}
function precacheAssets(workbox, options) {
if (options.preCaching.length) {
workbox.precaching.precacheAndRoute(options.preCaching, options.cacheOptions)
}
}
function runtimeCaching(workbox, options) {
const requestInterceptor = {
requestWillFetch({ request }) {
if (request.cache === 'only-if-cached' && request.mode === 'no-cors') {
return new Request(request.url, { ...request, cache: 'default', mode: 'no-cors' })
}
return request
},
fetchDidFail(ctx) {
ctx.error.message =
'[workbox] Network request for ' + ctx.request.url + ' threw an error: ' + ctx.error.message
console.error(ctx.error, 'Details:', ctx)
},
handlerDidError(ctx) {
ctx.error.message =
`[workbox] Network handler threw an error: ` + ctx.error.message
console.error(ctx.error, 'Details:', ctx)
return null
}
}
for (const entry of options.runtimeCaching) {
const urlPattern = new RegExp(entry.urlPattern)
const method = entry.method || 'GET'
const plugins = (entry.strategyPlugins || [])
.map(p => new (getProp(workbox, p.use))(...p.config))
plugins.unshift(requestInterceptor)
const strategyOptions = { ...entry.strategyOptions, plugins }
const strategy = new workbox.strategies[entry.handler](strategyOptions)
workbox.routing.registerRoute(urlPattern, strategy, method)
}
}
function offlinePage(workbox, options) {
if (options.offlinePage) {
// Register router handler for offlinePage
workbox.routing.registerRoute(new RegExp(options.pagesURLPattern), ({ request, event }) => {
const strategy = new workbox.strategies[options.offlineStrategy]
return strategy
.handle({ request, event })
.catch(() => caches.match(options.offlinePage))
})
}
}
function workboxExtensions(workbox, options) {
}
function cachingExtensions(workbox, options) {
}
function routingExtensions(workbox, options) {
}
store's index.js
export const state = () => ({});
export const actions = {
async nuxtServerInit({ dispatch, commit }, { res }) {
// initialize the store with user if already authenticated
if (res && res.locals && res.locals.user) {
const {
allClaims: claims,
idToken: token,
...authUser
} = res.locals.user;
await dispatch('auth/onAuthStateChangedAction', {
authUser,
claims,
token,
});
}
},
};

REST API auth error : WooCommerce

Been trying to fetch products from WooCommerce REST API now forever and my brain is bleeding :'( I followed all instructions on woocommerce and github/woocommerce and I can't for my life get anything in Postman with Basic Auth:
But when I select Auth 1.0 - I get all products:
But then if I take the Auth 1.0 generated URL and put it in my browser:
..Instructions under Authentication over HTTP (here) describes the parameters which are generated in URL automatically when i select Auth 1.0 in Postman - but how am I gonna generate those in my React component?
const APP_URL = 'http://0.0.0.0:80'
const CONSUMER_KEY = 'ck_xxxx'
const CONSUMER_SECRET = 'cs_xxxx'
const PRODUCT_URL = `${APP_URL}/wp-json/wc/v2/products?consumer_key=${CONSUMER_KEY}&consumer_secret=${CONSUMER_SECRET}`
fetch(PRODUCT_URL).then(res => {
if(res.status === 200){
return json
} else {
console.log("ERROR RESPONSE STATUS: " + status);
}
}).then( json => {
console.log(json)
})
})
So thankful for all input!
I think this problem may be solved by below code using "Interceptor" concept...
import {
Injectable,
// Injector
} from '#angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor,
HttpErrorResponse
} from '#angular/common/http';
// import { Router } from '#angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
// import { AuthService } from './auth.service';
import { config } from '../config/config';
#Injectable()
export class AppInterceptor implements HttpInterceptor {
constructor(
// private injector: Injector,
// private router: Router
) { }
private includeWooAuth(url) {
const wooAuth = `consumer_key=${config.consumerKey}&consumer_secret=${config.secretKey}`;
const hasQuery = url.includes('?');
let return_url = '';
if (hasQuery) {
return_url = wooAuth;
} else {
return_url = '?' + wooAuth;
}
return return_url;
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// const auth = this.injector.get(AuthService);
const authRequest = request.clone({
setHeaders: {
// Authorization: `Bearer ${auth.getToken()}`
},
url: `${config.basePath}/${request.url}${this.includeWooAuth(request.url)}`
});
return next.handle(authRequest)
.catch(err => {
if (err instanceof HttpErrorResponse && err.status === 0) {
console.log('Check Your Internet Connection And Try again Later');
} else if (err instanceof HttpErrorResponse && err.status === 401) {
// auth.setToken(null);
// this.router.navigate(['/', 'login']);
}
return Observable.throw(err);
});
}
}
This code will be kept into http.interceptor.ts. Obviously, you should initialize the consumer key and other details of woocommerce API into a constant variable. After that you create a service for show the list of the product like this:
retriveProducts(query: ProductQuery = {}): Observable<RetriveProductsResponse> {
return this.httpClient.get(`products`, {params: this.wooHelper.includeQuery(query), observe: 'response'})
.pipe(
map(value => this.wooHelper.includeResponseHeader(value)),
catchError(err => this.wooHelper.handleError(err)));
}
And call this service to the product.ts file like this:
getProducts() {
this.woocommerceProductsService.retriveProducts()
.subscribe(productResponse => {
this.products = productResponse.products;
}, error => this.errorMessage = <any>error);
}
I have used these above code into my project. I think it will help you.

Resources