Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QL Session Handler #88

Merged

Conversation

kidunot89
Copy link
Member

@kidunot89 kidunot89 commented Jun 20, 2019

Your checklist for this pull request

Thanks for sending a pull request! Please make sure you click the link above to view the contribution guidelines, then fill out the blanks below.

🚨Please review the guidelines for contributing to this repository.

  • Make sure you are making a pull request against the develop branch (left side). Also you should start your branch off our develop.
  • Make sure you are requesting to pull request from a topic/feature/bugfix branch (right side). Don't pull request from your master!

What does this implement/fix? Explain your changes.

Implements QL_Session_Handler and filters it in using the woocommerce_session_handler hook on GraphQL requests. It functions essentially the same as the core session handler with one key difference, instead of saving the session data to a cookie, it encrypts the data and saves it to a header. woocoommerce-session is the default header name but this can be alternated with a filter woocommerce_session_header_name.

In order to use the session header the valid unaltered session data must be passed as a header with the same name as the session header the data was retrieve from. Upon creation or changes to the session key, the session header is pass with the new value. When the session is destroyed, like when the user logs out, the session header is pass with the value 'false'.

It's recommend that when use the session header middleware and afterware functionality be leverage on the respective GraphQL client. See below for example of how to do with ApolloClient and the apollo-link library.

Example client-side implemention with ApolloClient

import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { ApolloLink } from 'apollo-link';

const httpLink = new HttpLink({
  uri: 'http://example.com/wordpress/graphql',
});

/**
 * Middleware operation
 * If we have a session token in localStorage, add it to the GraphQL request as a Session header.
 */
export const middleware = new ApolloLink((operation, forward) => {
  /**
   * If session data exist in local storage, set value as session header.
   */
  const session = localStorage.getItem('woo-session');
  if (session) {
    operation.setContext(({ headers = {} }) => ({
      headers: {
        'woocommerce-session': `Session ${session}`,
      }
    }));
  }

  return forward(operation);
});

/**
 * Afterware operation
 * This catches the incoming session token and stores it in localStorage, for future GraphQL requests.
 */
export const afterware = new ApolloLink((operation, forward) => {
  return forward(operation).map((response) => {
    /**
     * Check for session header and update session in local storage accordingly. 
     */
    const context = operation.getContext();
    const { response: { headers } } = context;
    const session = headers.get('woocommerce-session');
    if (session) {
      if ( localStorage.getItem('woo-session') !== session ) {
        localStorage.setItem('woo-session', headers.get('woocommerce-session'));
      }
    }

    return response;
  });
});

const client = new ApolloClient({
  link: middleware.concat(afterware.concat(httpLink)),
  cache,
  clientState: {},
});

Does this close any currently open issues?

Any relevant logs, error output, GraphiQL screenshots, etc?

(If it’s long, please paste to https://ghostbin.com/ and insert the link here.)

Any other comments?

Where has this been tested?

Operating System: Ubuntu 18.04

WordPress Version: 5.2

@kidunot89 kidunot89 added enhancement New feature or request work in progress Solution development in progress labels Jun 20, 2019
@kidunot89 kidunot89 self-assigned this Jun 20, 2019
@kidunot89 kidunot89 changed the title QL_Session_Handler QL Session Handler Jun 20, 2019
@MobyDigg
Copy link

@kidunot89 thanks for this. Is there an example with fetch() anywhere online?

@kidunot89
Copy link
Member Author

kidunot89 commented Nov 30, 2020

https://woographql.com/playground

The user login buttons in the GraphiQL component use fetch. You can see them in the docs/ app.

@MobyDigg
Copy link

image

…sorry, I can't find it @kidunot89

@kidunot89
Copy link
Member Author

@MobyDigg My bad, I haven't updated the Docs app since the WPGraphQL v1.0. I'll get it updated ASAP. Here is the React Component that implements the playground

@kidunot89
Copy link
Member Author

kidunot89 commented Nov 30, 2020

@MobyDigg The server has been updated, and the playground is working again

@muhaimincs
Copy link

@kidunot89 any example implementation using React-Native. I thought it should be the same but I keep getting a new woo-commerce session when query or mutation. How to resolve the keep changing woo-commerce session?

@leftis
Copy link

leftis commented Mar 22, 2021

@kidunot89 Question: Does the woocommerce-session returns on specific calls? For example addToCart mutation returns it?
I was working with it but then i altered something and broke it and can't find out what. I now get

{"errors":[{"debugMessage":"Call to a member function add_to_cart() on null","message":"Internal server error","extensions":{"category":"internal"},"locations":[{"line":2,"column":5}],"path":["addToCart"]}],"data":{"addToCart":null},"extensions":{"debug":[]}}

It looks like the response on add-to-cart mutation doesnt include the woocommerce-session. Any help on it please?

@kidunot89
Copy link
Member Author

kidunot89 commented Mar 22, 2021

@leftis You should get a woocommerce-session response header after addToCart, login, and registerCustomer. Also note that you can now get the session token using the following query

customer {
  sessionToken
}

@leftis
Copy link

leftis commented Mar 23, 2021

@leftis You should get a woocommerce-session response header after addToCart, login, and registerCustomer. Also note that you can now get the session token using the following query

customer {
  sessionToken
}

Don't know what I am doing wrong, it was working before upgrading on later versions but now for some reason it keeps returning

{"errors":[{"debugMessage":"Call to a member function add_to_cart() on null","message":"Internal server error","extensions":{"category":"internal"},"locations":[{"line":2,"column":5}],"path":["addToCart"]}],"data":{"addToCart":null},"extensions":{"debug":[]}}

is it a prerequisite to have the jwt plugin installed for the addToCart mutation to work?

@micmc422
Copy link

I have the exact same issue as @leftis, i try jwt plugin, cors plugins, but not efficient.

problem solved by deleting plugins via ftp and re-installing them on wordpress server.

hope it can help you.

@gsdavris
Copy link

gsdavris commented May 21, 2022

@kidunot89 @imranhsayed How to implement this on server side? when the locale storage is not available; (requests from api routes)

@amityweb
Copy link

amityweb commented May 7, 2024

Surprised I can't find much info about setting this up...

woocommerce-session is refreshed every time I send a query, though I include the previous one in the header:
headers: {'woocommerce-session': Session ${token} }

I assume it should stay the same? I am getting new sessions building up in the DB. Not sure what I am doing wrong.

@garydubb
Copy link

@amityweb I also have this trouble. Did you figure it out? I think, what is happening, every time a request is sent to graphql it creates a new session instead off handling with single, the above logic provides new session at every request. I tried using middleware to create session and store it in cookie and fetch is during apollo request , it is same thing, it seems something is missing when session data is being sent to woocommerce

@amityweb
Copy link

amityweb commented May 29, 2024

Edit: not sure if the following is related to the above but the following fixed my issue. It was because I was using the graphql editor to send test requests:

I did figure it out and I've been meaning to create an issue about because it's due to limitations in this plugin and I e wasted so much time on it.

In my case it's because this plugin does not provide a "headers" tab like all other GraphQL clients I use. So I've been posting the headers in the box under the graphql box (can't recall what it's called off the top of m head) but I assume that it dies NOT pass the parameters as actual headers. So my woocommerce-session token was not passed.

I had to install another GraphQL client to post data with, that does have a headers tab, and that worked.

Absolutely ridiculous this plugin provides a GraphQL interface but no means of passing "headers".

@garydubb
Copy link

@amityweb I understand what you mean. I will try to figure it out.

@amityweb
Copy link

I forgot to say, once I realised it was a limitation in this plugin that caused my issue, and I used a better GraphQL app to do my tests and could see the woocommerce-session was working OK, I then implemented it in my code, and the token is working OK. I use Axios on a Next.js project to post the request and the headers have to be submitted as heads in the GraphQL, not part of the main body request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants