Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ private static HttpContent CreateMultipartContent(
var fileContent = new StreamContent(file.OpenReadStream());
if (!string.IsNullOrEmpty(file.ContentType))
{
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
fileContent.Headers.TryAddWithoutValidation("Content-Type", file.ContentType);
}
Comment thread
michaelstaib marked this conversation as resolved.

form.Add(fileContent, i.ToString(), file.Name);
Expand Down Expand Up @@ -394,7 +394,7 @@ private static HttpContent CreateMultipartContent(
var fileContent = new StreamContent(fileInfo.File.OpenRead());
if (!string.IsNullOrEmpty(fileInfo.File.ContentType))
{
fileContent.Headers.ContentType = new MediaTypeHeaderValue(fileInfo.File.ContentType);
fileContent.Headers.TryAddWithoutValidation("Content-Type", fileInfo.File.ContentType);
}
Comment thread
michaelstaib marked this conversation as resolved.

form.Add(fileContent, fileInfo.Name, fileInfo.File.FileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -975,6 +975,7 @@ public async Task Get_Subscription_Over_SSE_With_Errors()
[Theory]
[InlineData((string?)null)]
[InlineData("application/pdf")]
[InlineData("text/plain; charset=utf-8")]
public async Task Post_GraphQL_FileUpload(string? contentType)
{
// arrange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,54 @@ public async Task Upload_Single_File()
await MatchSnapshotAsync(gateway, operation, result, rawRequest: rawRequest);
}

[Fact]
public async Task Upload_Single_File_Should_Forward_Parameterized_ContentType()
{
// arrange
using var server1 = CreateSourceSchema(
"A",
b => b.AddQueryType<SourceSchema1.Query>().AddUploadType());

using var gateway = await CreateCompositeSchemaAsync(
[
("A", server1)
]);

// act
using var client = GraphQLHttpClient.Create(gateway.CreateClient());

var stream = new MemoryStream("abc"u8.ToArray());
Comment thread
michaelstaib marked this conversation as resolved.
Dismissed

var operation = new OperationRequest(
"""
query ($file: Upload!) {
singleUpload(file: $file) {
fileName
contentType
content
}
}
""",
variables: new Dictionary<string, object?>
{
["file"] = new FileReference(() => stream, "test.txt", "text/plain; charset=utf-8")
});

RawRequest? rawRequest = null;
var request = new GraphQLHttpRequest(operation, new Uri("http://localhost:5000/graphql"))
{
Method = GraphQLHttpMethod.Post,
EnableFileUploads = true,
OnMessageCreated = (_, request, _) => rawRequest = GetRawRequest(request)
};

// act
var result = await client.SendAsync(request, TestContext.Current.CancellationToken);

// assert
await MatchSnapshotAsync(gateway, operation, result, rawRequest: rawRequest);
}

[Fact]
public async Task Upload_Single_File_In_Input_Object()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
title: Upload_Single_File_Should_Forward_Parameterized_ContentType
request:
contentType: multipart/form-data; boundary="f56524ab-5626-4955-b296-234a097b44f6"
body: |
--f56524ab-5626-4955-b296-234a097b44f6
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=operations

{"query":"query ($file: Upload!) {\n singleUpload(file: $file) {\n fileName\n contentType\n content\n }\n}","variables":{"file":null}}
--f56524ab-5626-4955-b296-234a097b44f6
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=map

{"0":["variables.file"]}
--f56524ab-5626-4955-b296-234a097b44f6
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=0; filename=test.txt; filename*=utf-8''test.txt

abc
--f56524ab-5626-4955-b296-234a097b44f6--
response:
body: |
{
"data": {
"singleUpload": {
"fileName": "test.txt",
"contentType": "text/plain; charset=utf-8",
"content": "abc"
}
}
}
sourceSchemas:
- name: A
schema: |
schema {
query: Query
}

type Query {
singleUpload(file: Upload!): FileUploadResult!
nullableUpload(file: Upload): FileUploadResult
singleUploadWithInput(input: FileInput!): FileUploadResult!
multiUpload(files: [Upload!]!): [FileUploadResult!]!
multiUploadWithInput(input: FilesInput!): [FileUploadResult!]!
}

type FileUploadResult {
fileName: String!
contentType: String
content: String!
}

input FileInput {
file: Upload!
}

input FilesInput {
files: [Upload!]!
}

"Defines the possible serialization types for GraphQL scalar values."
enum ScalarSerializationType {
"The scalar serializes to a string value."
STRING
"The scalar serializes to a boolean value."
BOOLEAN
"The scalar serializes to an integer value."
INT
"The scalar serializes to a floating-point value."
FLOAT
"The scalar serializes to an object value."
OBJECT
"The scalar serializes to a list value."
LIST
}

"The `Upload` scalar type represents a file upload."
scalar Upload @serializeAs(type: STRING)

directive @serializeAs(
"The primitive type a scalar is serialized to."
type: [ScalarSerializationType!]!
"The ECMA-262 regex pattern that the serialized scalar value conforms to."
pattern: String
) on SCALAR
interactions:
- request:
accept: application/graphql-response+json; charset=utf-8, application/json; charset=utf-8, application/jsonl; charset=utf-8, text/event-stream; charset=utf-8
contentType: multipart/form-data; boundary="f56524ab-5626-4955-b296-234a097b44f6"
body: |
--f56524ab-5626-4955-b296-234a097b44f6
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=operations

{"query":"query Op_6e1beb14_1($file: Upload!) {\n singleUpload(file: $file) {\n fileName\n contentType\n content\n }\n}","variables":{"file":null}}
--f56524ab-5626-4955-b296-234a097b44f6
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name=map

{"0":["variables.file"]}
--f56524ab-5626-4955-b296-234a097b44f6
Content-Type: text/plain; charset=utf-8
Content-Disposition: form-data; name=0; filename=test.txt; filename*=utf-8''test.txt

abc
--f56524ab-5626-4955-b296-234a097b44f6--
response:
results:
- |
{
"data": {
"singleUpload": {
"fileName": "test.txt",
"contentType": "text/plain; charset=utf-8",
"content": "abc"
}
}
}
operationPlan:
operation:
- document: |
query($file: Upload!) {
singleUpload(file: $file) {
fileName
contentType
content
}
}
hash: 6e1beb142822946e961b9f062df288a0
searchSpace: 1
expandedNodes: 1
nodes:
- id: 1
type: Operation
schema: A
operation: |
query Op_6e1beb14_1($file: Upload!) {
singleUpload(file: $file) {
fileName
contentType
content
}
}
forwardedVariables:
- file
requiresFileUpload: true
Loading