Giter Site home page Giter Site logo

Comments (8)

pavankjadda avatar pavankjadda commented on June 15, 2024 1

@martijnmelchers @viniciusverasdossantos @bahag-mersinlioglue Just now published version 14.0.0-beta.0 to NPM. Could you guys try it and let me know how it goes.

from ngx-cookie-service.

bahag-mersinlioglue avatar bahag-mersinlioglue commented on June 15, 2024

i tried to implement the ssr support in the same cookies service class. Here is my solution which i am using currently:


import {Inject, Injectable, Optional, PLATFORM_ID} from '@angular/core';
import {DOCUMENT, isPlatformBrowser} from '@angular/common';
import {REQUEST} from "@nguniversal/express-engine/tokens";
import {Request} from "express";

export type SameSite = 'Lax' | 'None' | 'Strict';

export interface CookieOptions {
expires?: number | Date;
path?: string;
domain?: string;
secure?: boolean;
sameSite?: SameSite;
}

@Injectable({
providedIn: 'root',
})
export class CookieService {
private readonly documentIsAccessible: boolean;

constructor(
    @Inject(DOCUMENT) private document: Document,
    // Get the `PLATFORM_ID` so we can check if we're in a browser.
    @Inject(PLATFORM_ID) private platformId: string,
    @Optional() @Inject(REQUEST) private request: Request
) {
    this.documentIsAccessible = isPlatformBrowser(this.platformId);
}

/**
 * Get cookie Regular Expression
 *
 * @param name Cookie name
 * @returns property RegExp
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
private static getCookieRegExp(name: string): RegExp {
    const escapedName: string = name.replace(/([\[\]\{\}\(\)\|\=\;\+\?\,\.\*\^\$])/gi, '\\$1');

    return new RegExp('(?:^' + escapedName + '|;\\s*' + escapedName + ')=(.*?)(?:;|$)', 'g');
}

/**
 * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).
 *
 * @param encodedURIComponent A value representing an encoded URI component.
 *
 * @returns The unencoded version of an encoded component of a Uniform Resource Identifier (URI).
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
private static safeDecodeURIComponent(encodedURIComponent: string): string {
    try {
        return decodeURIComponent(encodedURIComponent);
    } catch {
        // probably it is not uri encoded. return as is
        return encodedURIComponent;
    }
}

/**
 * Return `true` if {@link Document} is accessible, otherwise return `false`
 *
 * @param name Cookie name
 * @returns boolean - whether cookie with specified name exists
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
check(name: string): boolean {
    name = encodeURIComponent(name);
    const regExp: RegExp = CookieService.getCookieRegExp(name);
    return regExp.test(this.getPlatformCookies());
}

/**
 * Get cookies by name
 *
 * @param name Cookie name
 * @returns property value
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
get(name: string): string {
    if (this.check(name)) {
        name = encodeURIComponent(name);

        const regExp: RegExp = CookieService.getCookieRegExp(name);
        const result: RegExpExecArray | null = regExp.exec(this.getPlatformCookies());

        return result && result[1] ? CookieService.safeDecodeURIComponent(result[1]) : '';
    } else {
        return '';
    }
}

/**
 * Get all cookies in JSON format
 *
 * @returns all the cookies in json
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
getAll(): { [key: string]: string } {

    const cookies: { [key: string]: string } = {};
    const cookiesString: string = this.getPlatformCookies();

    if (cookiesString) {
        cookiesString.split(';').forEach((currentCookie: string) => {
            const [cookieName, cookieValue] = currentCookie.split('=');
            cookies[CookieService.safeDecodeURIComponent(cookieName.replace(/^ /, ''))] = CookieService.safeDecodeURIComponent(cookieValue);
        });
    }

    return cookies;
}

/**
 * Set cookie based on provided information
 *
 * @param name     Cookie name
 * @param value    Cookie value
 * @param expires  Number of days until the cookies expires or an actual `Date`
 * @param path     Cookie path
 * @param domain   Cookie domain
 * @param secure   Secure flag
 * @param sameSite OWASP samesite token `Lax`, `None`, or `Strict`. Defaults to `Lax`
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
set(
    name: string,
    value: string,
    expires?: CookieOptions['expires'],
    path?: CookieOptions['path'],
    domain?: CookieOptions['domain'],
    secure?: CookieOptions['secure'],
    sameSite?: SameSite
): void;

/**
 * Set cookie based on provided information
 *
 * Cookie's parameters:
 * <pre>
 * expires  Number of days until the cookies expires or an actual `Date`
 * path     Cookie path
 * domain   Cookie domain
 * secure   Secure flag
 * sameSite OWASP samesite token `Lax`, `None`, or `Strict`. Defaults to `Lax`
 * </pre>
 *
 * @param name     Cookie name
 * @param value    Cookie value
 * @param options  Body with cookie's params
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
set(name: string, value: string, options?: CookieOptions): void;

set(
    name: string,
    value: string,
    expiresOrOptions?: CookieOptions['expires'] | CookieOptions,
    path?: CookieOptions['path'],
    domain?: CookieOptions['domain'],
    secure?: CookieOptions['secure'],
    sameSite?: SameSite
): void {
    if (!this.documentIsAccessible) {
        return;
    }

    if (typeof expiresOrOptions === 'number' || expiresOrOptions instanceof Date || path || domain || secure || sameSite) {
        const optionsBody = {
            expires: expiresOrOptions as CookieOptions['expires'],
            path,
            domain,
            secure,
            sameSite: sameSite ? sameSite : 'Lax',
        };

        this.set(name, value, optionsBody);
        return;
    }

    let cookieString: string = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';';

    const options = expiresOrOptions ? expiresOrOptions : {};

    if (options.expires) {
        if (typeof options.expires === 'number') {
            const dateExpires: Date = new Date(new Date().getTime() + options.expires * 1000 * 60 * 60 * 24);

            cookieString += 'expires=' + dateExpires.toUTCString() + ';';
        } else {
            cookieString += 'expires=' + options.expires.toUTCString() + ';';
        }
    }

    if (options.path) {
        cookieString += 'path=' + options.path + ';';
    }

    if (options.domain) {
        cookieString += 'domain=' + options.domain + ';';
    }

    if (options.secure === false && options.sameSite === 'None') {
        options.secure = true;
        console.warn(
            `[ngx-cookie-service] Cookie ${name} was forced with secure flag because sameSite=None.` +
            `More details : https://github.com/stevermeister/ngx-cookie-service/issues/86#issuecomment-597720130`
        );
    }
    if (options.secure) {
        cookieString += 'secure;';
    }

    if (!options.sameSite) {
        options.sameSite = 'Lax';
    }

    cookieString += 'sameSite=' + options.sameSite + ';';

    // this.document.cookie = cookieString
    this.setPlatformCookies(cookieString);
}

/**
 * Delete cookie by name
 *
 * @param name   Cookie name
 * @param path   Cookie path
 * @param domain Cookie domain
 * @param secure Cookie secure flag
 * @param sameSite Cookie sameSite flag - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
delete(name: string, path?: CookieOptions['path'], domain?: CookieOptions['domain'], secure?: CookieOptions['secure'], sameSite: SameSite = 'Lax'): void {
    if (!this.documentIsAccessible) {
        return;
    }
    const expiresDate = new Date('Thu, 01 Jan 1970 00:00:01 GMT');
    this.set(name, '', {expires: expiresDate, path, domain, secure, sameSite});
}

/**
 * Delete all cookies
 *
 * @param path   Cookie path
 * @param domain Cookie domain
 * @param secure Is the Cookie secure
 * @param sameSite Is the cookie same site
 *
 * @author: Stepan Suvorov
 * @since: 1.0.0
 */
deleteAll(path?: CookieOptions['path'], domain?: CookieOptions['domain'], secure?: CookieOptions['secure'], sameSite: SameSite = 'Lax'): void {
    if (!this.documentIsAccessible) {
        return;
    }

    const cookies: any = this.getAll();

    for (const cookieName in cookies) {
        if (cookies.hasOwnProperty(cookieName)) {
            this.delete(cookieName, path, domain, secure, sameSite);
        }
    }
}

getPlatformCookies(): string {
    let cookies = '';
    if (this.documentIsAccessible) {
        cookies = this.document.cookie;
    } else {
        cookies =  this.request.headers.cookie != undefined ? this.request.headers.cookie : '';
    }
    return cookies;
}

setPlatformCookies(cookieString: string) {
    if (this.documentIsAccessible) {
        this.document.cookie = cookieString;
    } else {
        this.request.headers.cookie = cookieString;
    }
}

}

from ngx-cookie-service.

pavankjadda avatar pavankjadda commented on June 15, 2024

@martijnmelchers for some reason I didn't get notification for this issue. First, what error you see?

Second, we currently have 2 solutions (#214 and #206) for this and one of it will make it to production. I will keep the issue open and let you know the progress.

from ngx-cookie-service.

viniciusverasdossantos avatar viniciusverasdossantos commented on June 15, 2024

is there a solution yet?

from ngx-cookie-service.

pavankjadda avatar pavankjadda commented on June 15, 2024

is there a solution yet?

Haven't got a chance to work on this. But current version 14.0.0 should work with SSR and shows login page for brief period of time and we are working to fix this.

from ngx-cookie-service.

martijnmelchers avatar martijnmelchers commented on June 15, 2024

is there a solution yet?

Haven't got a chance to work on this. But current version 14.0.0 should work with SSR and shows login page for brief period of time and we are working to fix this.

You should check out other libraries doing the same. We've been using ngx-cookie for a while now and it's been working fine. However 6.0 broke because of a parsing error. Our only hold back to switching to this library is a stable working SSR version

from ngx-cookie-service.

pavankjadda avatar pavankjadda commented on June 15, 2024

is there a solution yet?

Haven't got a chance to work on this. But current version 14.0.0 should work with SSR and shows login page for brief period of time and we are working to fix this.

You should check out other libraries doing the same. We've been using ngx-cookie for a while now and it's been working fine. However 6.0 broke because of a parsing error. Our only hold back to switching to this library is a stable working SSR version

Understood. BTW SSR always worked in this library v12, v13 etc... We are in the process of adding dedicated SSR support

from ngx-cookie-service.

pavankjadda avatar pavankjadda commented on June 15, 2024

I am closing since I have not heard from anyone. If anyone finds this comment, you can install SSR version of the library and usage guide here

from ngx-cookie-service.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.