Movatterモバイル変換


[0]ホーム

URL:


Skip to main content
🧑🏽‍🔬 We're testing new AI and search tools ondocs-next.strapi.io! Feel free to have a look andshare your feedback
  • API calls
  • CRON jobs
  • Environment variables
  • Features
  • Middlewares
  • Plugins
  • Server
  • GraphQL plugin

    By default Strapi createREST endpoints for each of your content-types. The GraphQL plugin adds a GraphQL endpoint to fetch and mutate your content. With the GraphQL plugin installed, you can use the Apollo Server-based GraphQL Sandbox to interactively build your queries and mutations and read documentation tailored to your content types.

    IDENTITY CARD
    Location
    Usable via the admin panel.
    Configured through both admin panel and server code, with different sets of options.
    Package name
    @strapi/plugin-graphql
    Additional resources
    GraphQL playground use exampleGraphQL playground use example

    Installation

    To install the GraphQL plugin, run the following command in your terminal:

    • Yarn
    • NPM
    yarnadd @strapi/plugin-graphql

    Once installed, the GraphQL sandbox is accessible at the/graphql URL and can be used to interactively build your queries and mutations and read documentation tailored to your content-types.

    Once the plugin is installed, theGraphQL Sandbox is accessible at the/graphql route (e.g.,localhost:1337/graphql) when your Strapi application server is running.

    Configuration

    Most configuration options for the Documentation plugin are handled via your Strapi project's code, though the GraphQL playground also offers some non-specific Strapi settings.

    Admin panel settings

    The Strapi admin panel does not provide Strapi-specific settings for the GraphQL plugin. However, the GraphQL Playground accessible at the/graphql route is an embedded Apollo Server playground, so it includes all configuration and settings available with such an instance. Please refer to the officialGraphQL playground documentation for details.

    Code-based configuration

    Plugins configuration are defined intheconfig/plugins.js file. This configuration file can include agraphql.config object to define specific configurations for the GraphQL plugin.

    Available options

    Apollo Server options can be passed directly to Apollo with thegraphql.config.apolloServer configuration object. Apollo Server options can be used for instance to enable thetracing feature, which is supported by the GraphQL Sandbox to track the response time of each part of your query. TheApollo Server default cache option iscache: 'bounded'. You can change it in theapolloServer configuration. For more information visitApollo Server Docs.

    The GraphQL plugin has the following specific configuration options that should be declared in agraphql.config object within theconfig/plugins file. All parameters are optional:

    OptionTypeDescriptionDefault ValueNotes
    endpointStringSets the GraphQL endpoint path.'/graphql'Example:/custom-graphql
    shadowCRUDBooleanEnables or disables automatic schema generation for content types.true
    depthLimitNumberLimits the depth of GraphQL queries to prevent excessive nesting.10Use this to mitigate potential DoS attacks.
    amountLimitNumberLimits the maximum number of items returned in a single response.100Use cautiously to avoid performance issues.
    playgroundAlwaysBoolean[Deprecated] Enables GraphQL Playground in all environments (deprecated).falsePrefer usinglandingPage instead.
    landingPageBoolean | FunctionEnables or disables the landing page for GraphQL. Accepts a boolean or a function returning a boolean or an ApolloServerPlugin implementingrenderLandingPage.false in production,true in other environments
    apolloServerObjectPasses configuration options directly to Apollo Server.{}Example:{ tracing: true }
    Caution

    The maximum number of items returned by the response is limited to 100 by default. This value can be changed using theamountLimit configuration option, but should only be changed after careful consideration: a large query can cause a DDoS (Distributed Denial of Service) and may cause abnormal load on your Strapi server, as well as your database server.

    Note

    The GraphQL Sandbox is enabled by default in all environments except production. Set thelandingPage configuration option totrue to also enable the GraphQL Sandbox in production environments.

    The following is an example custom configuration:

    • JavaScript
    • TypeScript
    /config/plugins.js
    module.exports={
    graphql:{
    config:{
    endpoint:'/graphql',
    shadowCRUD:true,
    landingPage:false,// disable Sandbox everywhere
    depthLimit:7,
    amountLimit:100,
    apolloServer:{
    tracing:false,
    },
    },
    },
    };

    Dynamically enable Apollo Sandbox

    You can use a function to dynamically enable Apollo Sandbox depending on the environment:

    • JavaScript
    • TypeScript
    ./config/plugins.js
    module.exports=({ env})=>{
    graphql:{
    config:{
    endpoint:'/graphql',
    shadowCRUD:true,
    landingPage:(strapi)=>{
    if(env("NODE_ENV")!=="production"){
    returntrue;
    }else{
    returnfalse;
    }
    },
    },
    },
    };

    CORS exceptions for Landing Page

    If the landing page is enabled in production environments (which is not recommended), CORS headers for the Apollo Server landing page must be added manually.

    To add them globally, you can merge the following into your middleware configuration:

    /config/middlewares
    {
    name:"strapi::security",
    config:{
    contentSecurityPolicy:{
    useDefaults:true,
    directives:{
    "connect-src":["'self'","https:","apollo-server-landing-page.cdn.apollographql.com"],
    "img-src":["'self'","data:","blob:","apollo-server-landing-page.cdn.apollographql.com"],
    "script-src":["'self'","'unsafe-inline'","apollo-server-landing-page.cdn.apollographql.com"],
    "style-src":["'self'","'unsafe-inline'","apollo-server-landing-page.cdn.apollographql.com"],
    "frame-src":["sandbox.embed.apollographql.com"]
    }
    }
    }
    }

    To add these exceptions only for the/graphql path (recommended), you can create a new middleware to handle it. For example:

    • JavaScript
    • TypeScript
    ./middlewares/graphql-security.js
    module.exports=(config,{ strapi})=>{
    returnasync(ctx, next)=>{
    if(ctx.request.path==='/graphql'){
    ctx.set('Content-Security-Policy',"default-src 'self'; script-src 'self' 'unsafe-inline' cdn.jsdelivr.net apollo-server-landing-page.cdn.apollographql.com; connect-src 'self' https:; img-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; media-src 'self' data: blob: apollo-server-landing-page.cdn.apollographql.com; frame-src sandbox.embed.apollographql.com; manifest-src apollo-server-landing-page.cdn.apollographql.com;");
    }
    awaitnext();
    };
    };

    Shadow CRUD

    To simplify and automate the build of the GraphQL schema, we introduced the Shadow CRUD feature. It automatically generates the type definitions, queries, mutations and resolvers based on your models.

    Example:

    If you've generated an API calledDocument usingthe interactivestrapi generate CLI or the administration panel, your model looks like this:

    /src/api/[api-name]/content-types/document/schema.json

    {
    "kind":"collectionType",
    "collectionName":"documents",
    "info":{
    "singularName":"document",
    "pluralName":"documents",
    "displayName":"document",
    "name":"document"
    },
    "options":{
    "draftAndPublish":true
    },
    "pluginOptions":{},
    "attributes":{
    "name":{
    "type":"string"
    },
    "description":{
    "type":"richtext"
    },
    "locked":{
    "type":"boolean"
    }
    }
    }
    Generated GraphQL type and queries
    # Document's Type definition
    inputDocumentFiltersInput{
    name:StringFilterInput
    description:StringFilterInput
    locked:BooleanFilterInput
    createdAt:DateTimeFilterInput
    updatedAt:DateTimeFilterInput
    publishedAt:DateTimeFilterInput
    and:[DocumentFiltersInput]
    or:[DocumentFiltersInput]
    not:DocumentFiltersInput
    }

    inputDocumentInput{
    name:String
    description:String
    locked:Boolean
    createdAt:DateTime
    updatedAt:DateTime
    publishedAt:DateTime
    }

    typeDocument{
    name:String
    description:String
    locked:Boolean
    createdAt:DateTime
    updatedAt:DateTime
    publishedAt:DateTime
    }

    typeDocumentEntity{
    id:ID
    attributes:Document
    }

    typeDocumentEntityResponse{
    data:DocumentEntity
    }

    typeDocumentEntityResponseCollection{
    data:[DocumentEntity!]!
    meta:ResponseCollectionMeta!
    }

    typeDocumentRelationResponseCollection{
    data:[DocumentEntity!]!
    }

    # Queries to retrieve one or multiple restaurants.
    typeQuery{
    document(id:ID):DocumentEntityResponse
    documents(
    filters:DocumentFiltersInput
    pagination:PaginationArg={}
    sort:[String]=[]
    publicationState:PublicationState=LIVE
    ):DocumentEntityResponseCollection
    }

    # Mutations to create, update or delete a restaurant.
    typeMutation{
    createDocument(data:DocumentInput!):DocumentEntityResponse
    updateDocument(id:ID!,data:DocumentInput!):DocumentEntityResponse
    deleteDocument(id:ID!):DocumentEntityResponse
    }

    Customization

    Strapi provides a programmatic API to customize GraphQL, which allows:

    Example of GraphQL customizations
    • JavaScript
    • TypeScript
    /src/index.js

    module.exports={
    /**
    * An asynchronous register function that runs before
    * your application is initialized.
    *
    * This gives you an opportunity to extend code.
    */
    register({ strapi}){
    const extensionService= strapi.plugin('graphql').service('extension');

    extensionService.shadowCRUD('api::restaurant.restaurant').disable();
    extensionService.shadowCRUD('api::category.category').disableQueries();
    extensionService.shadowCRUD('api::address.address').disableMutations();
    extensionService.shadowCRUD('api::document.document').field('locked').disable();
    extensionService.shadowCRUD('api::like.like').disableActions(['create','update','delete']);

    constextension=({ nexus})=>({
    // Nexus
    types:[
    nexus.objectType({
    name:'Book',
    definition(t){
    t.string('title');
    },
    }),
    ],
    plugins:[
    nexus.plugin({
    name:'MyPlugin',
    onAfterBuild(schema){
    console.log(schema);
    },
    }),
    ],
    // GraphQL SDL
    typeDefs:`
    type Article {
    name: String
    }
    `,
    resolvers:{
    Query:{
    address:{
    resolve(){
    return{value:{city:'Montpellier'}};
    },
    },
    },
    },
    resolversConfig:{
    'Query.address':{
    auth:false,
    },
    },
    });
    extensionService.use(extension);
    },
    };
    Disabling operations in the Shadow CRUD

    Theextension service provided with the GraphQL plugin exposes functions that can be used to disable operations on Content-Types:

    Content-type functionDescriptionArgument typePossible argument values
    disable()Fully disable the Content-Type--
    disableQueries()Only disable queries for the Content-Type--
    disableMutations()Only disable mutations for the Content-Type--
    disableAction()Disable a specific action for the Content-TypeStringOne value from the list:
    • create
    • find
    • findOne
    • update
    • delete
    disableActions()Disable specific actions for the Content-TypeArray of StringsMultiple values from the list:
    • create
    • find
    • findOne
    • update
    • delete

    Actions can also be disabled at the field level, with the following functions:

    Field functionDescription
    disable()Fully disable the field
    disableOutput()Disable the output on a field
    disableInput()Disable the input on a field
    disableFilters()Disable filters input on a field

    Examples:

    // Disable the 'find' operation on the 'restaurant' content-type in the 'restaurant' API
    strapi
    .plugin('graphql')
    .service('extension')
    .shadowCRUD('api::restaurant.restaurant')
    .disableAction('find')

    // Disable the 'name' field on the 'document' content-type in the 'document' API
    strapi
    .plugin('graphql')
    .service('extension')
    .shadowCRUD('api::document.document')
    .field('name')
    .disable()
    Using getters

    The following getters can be used to retrieve information about operations allowed on content-types:

    Content-type getterDescriptionArgument typePossible argument values
    isEnabled()Returns whether a content-type is enabled--
    isDisabled()Returns whether a content-type is disabled--
    areQueriesEnabled()Returns whether queries are enabled on a content-type--
    areQueriesDisabled()Returns whether queries are disabled on a content-type--
    areMutationsEnabled()Returns whether mutations are enabled on a content-type--
    areMutationsDisabled()Returns whether mutations are disabled on a content-type--
    isActionEnabled(action)Returns whether the passedaction is enabled on a content-typeStringOne value from the list:
    • create
    • find
    • findOne
    • update
    • delete
    isActionDisabled(action)Returns whether the passedaction is disabled on a content-typeStringOne value from the list:
    • create
    • find
    • findOne
    • update
    • delete

    The following getters can be used to retrieve information about operations allowed on fields:

    Field getterDescription
    isEnabled()Returns whether a field is enabled
    isDisabled()Returns whether a field is disabled
    hasInputEnabled()Returns whether a field has input enabled
    hasOutputEnabled()Returns whether a field has output enabled
    hasFiltersEnabled()Returns whether a field has filtering enabled
    Extending the schema

    The schema generated by the Content API can be extended by registering an extension.

    This extension, defined either as an object or a function returning an object, will be used by theuse() function exposed by theextensionservice provided with the GraphQL plugin.

    The object describing the extension accepts the following parameters:

    ParameterTypeDescription
    typesArrayAllows extending the schema types usingNexus-based type definitions
    typeDefsStringAllows extending the schema types usingGraphQL SDL
    pluginsArrayAllows extending the schema using Nexusplugins
    resolversObjectDefines custom resolvers
    resolversConfigObjectDefinesconfiguration options for the resolvers, such asauthorization,policies andmiddlewares
    Tip

    Thetypes andplugins parameters are based onNexus. To use them, register the extension as a function that takesnexus as a parameter:

    Example:
    • JavaScript
    • TypeScript
    /src/index.js

    module.exports={
    register({ strapi}){
    constextension=({ nexus})=>({
    types:[
    nexus.objectType({

    }),
    ],
    plugins:[
    nexus.plugin({

    })
    ]
    })

    strapi.plugin('graphql').service('extension').use(extension)
    }
    }
    Custom configuration for resolvers

    A resolver is a GraphQL query or mutation handler (i.e. a function, or a collection of functions, that generate(s) a response for a GraphQL query or mutation). Each field has a default resolver.

    Whenextending the GraphQL schema, theresolversConfig key can be used to define a custom configuration for a resolver, which can include:

    Authorization configuration

    By default, the authorization of a GraphQL request is handled by the registered authorization strategy that can be eitherAPI token or through theUsers & Permissions plugin. The Users & Permissions plugin offers a more granular control.

    Authorization with the Users & Permissions plugin

    With the Users & Permissions plugin, a GraphQL request is allowed if the appropriate permissions are given.

    For instance, if a 'Category' content-type exists and is queried through GraphQL with theQuery.categories handler, the request is allowed if the appropriatefind permission for the 'Categories' content-type is given.

    To query a single category, which is done with theQuery.category handler, the request is allowed if the thefindOne permission is given.

    Please refer to the user guide on how todefine permissions with the Users & Permissions plugin.

    To change how the authorization is configured, use the resolver configuration defined atresolversConfig.[MyResolverName]. The authorization can be configured:

    • either withauth: false to fully bypass the authorization system and allow all requests,
    • or with ascope attribute that accepts an array of strings to define the permissions required to authorize the request.
    Examples of authorization configuration
    • JavaScript
    • TypeScript
    /src/index.js

    module.exports={
    register({ strapi}){
    const extensionService= strapi.plugin('graphql').service('extension');

    extensionService.use({
    resolversConfig:{
    'Query.categories':{
    /**
    * Querying the Categories content-type
    * bypasses the authorization system.
    */
    auth:false
    },
    'Query.restaurants':{
    /**
    * Querying the Restaurants content-type
    * requires the find permission
    * on the 'Address' content-type
    * of the 'Address' API
    */
    auth:{
    scope:['api::address.address.find']
    }
    },
    }
    })
    }
    }

    Policies

    Policies can be applied to a GraphQL resolver through theresolversConfig.[MyResolverName].policies key.

    Thepolicies key is an array accepting a list of policies, each item in this list being either a reference to an already registered policy or an implementation that is passed directly (seepolicies configuration documentation).

    Policies directly implemented inresolversConfig are functions that take acontext object and thestrapi instance as arguments.Thecontext object gives access to:

    • theparent,args,context andinfo arguments of the GraphQL resolver,
    • Koa'scontext withcontext.http andstate withcontext.state.
    Example of GraphQL policies applied to resolvers
    • JavaScript
    • TypeScript
    /src/index.js

    module.exports={
    register({ strapi}){
    const extensionService= strapi.plugin('graphql').service('extension');

    extensionService.use({
    resolversConfig:{
    'Query.categories':{
    policies:[
    (context,{ strapi})=>{
    console.log('hello', context.parent)
    /**
    * If 'categories' have a parent, the function returns true,
    * so the request won't be blocked by the policy.
    */
    return context.parent!==undefined;
    }
    /**
    * Uses a policy already created in Strapi.
    */
    "api::model.policy-name",

    /**
    * Uses a policy already created in Strapi with a custom configuration
    */
    {name:"api::model.policy-name",config:{/* all config values I want to pass to the strapi policy */}},
    ],
    auth:false,
    },
    }
    })
    }
    }
    Middlewares

    Middlewares can be applied to a GraphQL resolver through theresolversConfig.[MyResolverName].middlewares key. The only difference between the GraphQL and REST implementations is that theconfig key becomesoptions.

    Themiddlewares key is an array accepting a list of middlewares, each item in this list being either a reference to an already registered middleware or an implementation that is passed directly (seemiddlewares configuration documentation).

    Middlewares directly implemented inresolversConfig can take the GraphQL resolver's`parent`, `args`, `context` and `info` objects as arguments.

    Tip

    Middlewares with GraphQL can even act on nested resolvers, which offer a more granular control than with REST.

    Examples of GraphQL middlewares applied to a resolver
    • JavaScript
    • TypeScript

    module.exports={
    register({ strapi}){
    const extensionService= strapi.plugin('graphql').service('extension');

    extensionService.use({
    resolversConfig:{
    'Query.categories':{
    middlewares:[
    /**
    * Basic middleware example #1
    * Log resolving time in console
    */
    async(next, parent, args, context, info)=>{
    console.time('Resolving categories');

    // call the next resolver
    const res=awaitnext(parent, args, context, info);

    console.timeEnd('Resolving categories');

    return res;
    },
    /**
    * Basic middleware example #2
    * Enable server-side shared caching
    */
    async(next, parent, args, context, info)=>{
    info.cacheControl.setCacheHint({maxAge:60,scope:"PUBLIC"});
    returnnext(parent, args, context, info);
    },
    /**
    * Basic middleware example #3
    * change the 'name' attribute of parent with id 1 to 'foobar'
    */
    (resolve, parent,...rest)=>{
    if(parent.id===1){
    returnresolve({...parent,name:'foobar'},...rest);
    }

    returnresolve(parent,...rest);
    }
    /**
    * Basic middleware example #4
    * Uses a middleware already created in Strapi.
    */
    "api::model.middleware-name",

    /**
    * Basic middleware example #5
    * Uses a middleware already created in Strapi with a custom configuration
    */
    {name:"api::model.middleware-name",options:{/* all config values I want to pass to the strapi middleware */}},
    ],
    auth:false,
    },
    }
    })
    }
    }
    Security

    GraphQL is a query language allowing users to use a broader panel of inputs than traditional REST APIs. GraphQL APIs are inherently prone to security risks, such as credential leakage and denial of service attacks, that can be reduced by taking appropriate precautions.

    Disable introspection and Sandbox in production

    In production environments, disabling the GraphQL Sandbox and the introspection query is strongly recommended.If you haven't edited theconfiguration file, it is already disabled in production by default.

    Limit max depth and complexity

    A malicious user could send a query with a very high depth, which could overload your server. Use thedepthLimitconfiguration parameter to limit the maximum number of nested fields that can be queried in a single request. By default,depthLimit is set to 10 but can be set to a higher value during testing and development.

    Tip

    To increase GraphQL security even further, 3rd-party tools can be used. See the guide aboutusing GraphQL Armor with Strapi on the forum.

    Usage

    The GraphQL plugin adds a GraphQL endpoint accessible and provides access to a GraphQL playground, accessing at the/graphql route of the Strapi admin panel, to interactively build your queries and mutations and read documentation tailored to your content types. For detailed instructions on how to use the GraphQL Playground, please refer to the officialApollo Server documentation.

    Usage with the Users & Permissions feature

    TheUsers & Permissions feature allows protecting the API with a full authentication process.

    Registration

    Usually you need to sign up or register before being recognized as a user then perform authorized requests.

    Mutation
    mutation{
    register(input:{username:"username",email:"email",password:"password"}){
    jwt
    user{
    username
    email
    }
    }
    }

    You should see a new user is created in theUsers collection type in your Strapi admin panel.

    Authentication

    To perform authorized requests, you must first get a JWT:

    Mutation
    mutation{
    login(input:{identifier:"email",password:"password"}){
    jwt
    }
    }

    Then on each request, send along anAuthorization header in the form of{ "Authorization": "Bearer YOUR_JWT_GOES_HERE" }. This can be set in the HTTP Headers section of your GraphQL Sandbox.

    Usage with API tokens

    To use API tokens for authentication, pass the token in theAuthorization header using the formatBearer your-api-token.

    Note

    Using API tokens in the the GraphQL Sandbox requires adding the authorization header with your token in theHTTP HEADERS tab:

    {
    "Authorization" : "Bearer <TOKEN>"
    }

    Replace<TOKEN> with your API token generated in the Strapi Admin panel.

    GraphQL API

    The GraphQL plugin adds a GraphQL endpoint that can accessed through Strapi's GraphQL API:


    [8]ページ先頭

    ©2009-2025 Movatter.jp