GraphQL Array Arguments
以下を希望される場合:
- コードの貢献を提出する
- バグの報告または修正
- 機能や改善の提案
- ドキュメントへの貢献
これらのページの英語版のガイドラインに従ってください。
このページの英語版にアクセスしてください。
Array Argument Validation in GraphQL
Overview
All array arguments in GitLab GraphQL API should have size validation to prevent abuse and performance issues.
Validation Approaches
Recommended: Explicit Validation (Target State)
Use the validates option to explicitly declare array size limits:
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } },
description: "Usernames of users assigned to the merge request " \
"(maximum is #{Types::BaseArgument::MAX_ARRAY_SIZE} usernames)."Benefits:
- Clear and explicit
- Visible in the argument definition
- Consistent with existing codebase patterns
- Uses GraphQL-Ruby’s built-in validation
Automatic Validation (Transition Period)
During the transition period, array arguments without explicit validates: { length: { maximum: ... } } will automatically be limited to 100 items by BaseArgument.
# This will automatically be limited to 100 items
argument :items, [GraphQL::Types::String],
required: false,
description: 'List of items.'How It Works
The BaseArgument class implements smart detection:
- If explicit validation exists: Uses the explicit limit (no automatic validation)
- If no explicit validation: Applies automatic 100-item limit
# Explicit validation - uses 50 as the limit
argument :limited_items, [GraphQL::Types::String],
validates: { length: { maximum: 50 } },
description: 'Limited to 50 items.'
# No explicit validation - automatically limited to 100 items
argument :auto_limited_items, [GraphQL::Types::String],
description: 'Automatically limited to 100 items.'Migration Path
Step 1: Automatic Protection (Current)
All array arguments are automatically protected with a 100-item limit.
Step 2: Add Explicit Validation
Gradually add explicit validates declarations to all array arguments:
# Before (relies on automatic validation)
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
description: 'Usernames of users assigned to the merge request.'
# After (explicit validation)
argument :assignee_usernames, [GraphQL::Types::String],
required: false,
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } },
description: "Usernames of users assigned to the merge request " \
"(maximum is #{Types::BaseArgument::MAX_ARRAY_SIZE} usernames)."Step 3: Remove Automatic Validation
Once all array arguments have explicit validation, we can remove the automatic validation from BaseArgument.
Constants
Types::BaseArgument::MAX_ARRAY_SIZE
Default maximum size for array arguments (currently 100).
Use this constant for consistency:
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } }Custom Limits
For specific use cases, you can use a different limit:
# Using a module constant
module WorkItems
module SharedFilterArguments
MAX_FIELD_LIMIT = 100
end
end
argument :ids, [::Types::GlobalIDType[::WorkItem]],
validates: { length: { maximum: WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT } },
description: "Filter by global IDs (maximum is #{WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT} IDs)."Error Messages
When validation fails, users receive a clear error message:
"assigneeUsernames cannot accept more than 100 items"Examples
Good Examples
# Example 1: Using the default constant
argument :user_ids, [GraphQL::Types::ID],
validates: { length: { maximum: Types::BaseArgument::MAX_ARRAY_SIZE } },
description: "User IDs (maximum is #{Types::BaseArgument::MAX_ARRAY_SIZE})."
# Example 2: Using a custom constant
argument :label_names, [GraphQL::Types::String],
validates: { length: { maximum: WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT } },
description: "Label names (maximum is #{WorkItems::SharedFilterArguments::MAX_FIELD_LIMIT})."
# Example 3: Custom limit for specific use case
argument :vulnerability_ids, [GraphQL::Types::ID],
validates: { length: { minimum: 1, maximum: 50 } },
description: "Vulnerability IDs (minimum 1, maximum 50)."Bad Examples
# Bad: No validation and no description of limit
argument :items, [GraphQL::Types::String],
description: 'List of items.'
# Bad: Hardcoded number without constant
argument :items, [GraphQL::Types::String],
validates: { length: { maximum: 100 } },
description: 'List of items (maximum is 100).'Testing
When testing resolvers or mutations with array arguments, test the validation:
RSpec.describe Resolvers::MyResolver do
it 'accepts arrays within the limit' do
items = Array.new(50, 'item')
expect { resolve(items: items) }.not_to raise_error
end
it 'rejects arrays exceeding the limit' do
items = Array.new(101, 'item')
expect { resolve(items: items) }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end