I'm trying to upload a file to a server and I keep getting a error response code of -1.
This is for a NativeScript app built with Angular and I'm using the NativeScript HTTP Background plugin.
component.ts
onCreateRecipe() {
console.log(this.imageUris);
const recipeForm = {
name: this.form.get('name').value,
description: this.form.get('description').value,
photo: this.imageUris[0],
ingredients: this.form.get('ingredients').value,
// steps: this.form.get('steps').value,
// tag: 'poultry recipe'
type: this.recipeType
};
console.log(recipeForm);
this.apiService.postRecipe(recipeForm).subscribe(res => console.log(res));
}
service.ts
postRecipe(recipe) {
const session = bghttp.session('image-upload');
const subject = new Subject<any>();
const request = {
url: `${this.apiURL}/recipe/1`,
method: 'POST',
headers: {
"Content-Type": "application/octet-stream"
},
description: 'test'
};
let task: bghttp.Task;
const params = [
{ name: 'name', value: recipe.name },
{ name: 'description', value: recipe.description },
{ name: 'photo', filename: recipe.photo, mimeType: 'image/png' },
{ name: 'ingredients', value: JSON.stringify(recipe.ingredients) }
];
console.log(params);
task = session.multipartUpload(params, request);
task.on('responded', (event: any) => {
if (event.data && event.data.error) {
subject.error(event.data);
} else {
subject.next(event.data);
}
});
// task.on('error', (event) => subject.error(event));
task.on('error', (e) =>console.log("received " + e.responseCode + " code."));
return subject;
}
Note: ingredients is a FormArray that's why I have to use JSON.Stringify to pass it to the plugin. recipe.photo is a file path to the image.
I expect all the data, including the image file, to be uploaded to the server but right now only the image is being uploaded.
Related
I got empty object while uploading image. I follow all the step provided, but still can't make it solve. The error said "Variable "$file" got invalid value {}; Upload value invalid."
const client = createClient({
url: import.meta.env.VITE_BASE_API_URL ?? '',
exchanges: [
...defaultExchanges,
dedupExchange,
cacheExchange,
subscriptionExchange({
forwardSubscription: (operation) => ({
subscribe: (sink) => ({
unsubscribe: wsClient.subscribe(operation, sink),
}),
}),
}),
refocusExchange(),
multipartFetchExchange,
],
});
export const UPLOAD_WORKER_IMAGE = gql`
mutation setImage($file: Upload!, $workerId: UUID!) {
updateWorker(input: { patch: { imageUrl: $file }, id: $workerId }) {
}
}
}
`;
// Upload.tsx
const [, mutateWorkerImage] = useMutation<UpdateWorker>(UPLOAD_WORKER_IMAGE);
const file = bindData.avatarFile;
const { error: errorUploadImage, data } = await mutateWorkerImage({
workerId: dataWorker.createWorker.worker.id,
file: file,
});
as per the title, I am having problem trying to enable graphql subscription in my loopback 4 application.
Here is my code that I've done so far.
index.ts
export async function main(options: ApplicationConfig = {}) {
const app = new BackendLb4Application(options)
await app.boot()
await app.start()
const url = app.restServer.url;
const oas: Oas3 = <Oas3><unknown>await app.restServer.getApiSpec()
const {schema} = await createGraphQLSchema(oas, {
operationIdFieldNames: true,
baseUrl: url,
createSubscriptionsFromCallbacks: true,
})
const handler = graphqlHTTP( (request:any, response:any, graphQLParams: any) => ({
schema,
pretty: true,
graphiql: true
}))
app.mountExpressRouter(graphqlPath, handler);
const pubsub = new PubSub()
const ws = createServer(app);
ws.listen(PORT, () => {
new SubscriptionServer(
{
execute,
subscribe,
schema,
onConnect: (params: any, socket: any, ctx: any) => {
console.log(params, 'here on onconnect')
// Add pubsub to context to be used by GraphQL subscribe field
return { pubsub }
}
},
{
server: ws,
path: '/subscriptions'
}
)
})
return app
}
Here is my schema
type Subscription {
"""
Equivalent to PATCH onNotificationUpdate
"""
postRequestQueryCallbackUrlApiNotification(secondInputInput: SecondInputInput): String
"""
Equivalent to PATCH onNotificationUpdate
"""
postRequestQueryCallbackUrlOnNotificationUpdate(firstInputInput: FirstInputInput): String
}
Here is an example of my controller
#patch('/notification-update', {
operationId: 'notificationUpdate',
description: '**GraphQL notificationUpdate**',
callbacks:[ {
onNotificationUpdate: {
//'{$request.query.callbackUrl}/onNotificationUpdate': {
post: {
requestBody: {
operationId: 'notificationUpdateCallback',
description: 'rasjad',
content: {
'application/json': {
schema: {
title: "firstInput",
type: 'object',
properties: {
userData: {
type: "string"
}
}
}
}
}
},
responses: {
'200': {
description: 'response to subscription',
}
}
}
},
// }
}],
responses: {
'200': {
description: 'Notification PATCH success count',
content: {'application/json': {schema: CountSchema}},
},
},
})
async updateAll(
#requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(Notification, {partial: true}),
},
},
})
notification: Notification,
#param.where(Notification) where?: Where<Notification>,
): Promise<Count> {
return this.notificationRepository.update(notification, where);
}
Ive defined the callbacks object in my controller which will then create a subscription in my schema. Tested it out on graphiql but did not work.
I am not sure where to go from here. Do I need a custom resolver or something? Not sure.
Appreciate it if anyone could help on this.
Just in case someone else is looking to do the same thing.
I switched out graphqlHTTP with Apollo Server to create my graphql server.
So my final index.ts looks like this.
export async function main(options: ApplicationConfig = {}) {
const lb4Application = new BackendLb4Application(options)
await lb4Application.boot()
await lb4Application.migrateSchema()
await lb4Application.start()
const url = lb4Application.restServer.url;
const graphqlPath = '/graphql'
// Get the OpenApiSpec
const oas: Oas3 = <Oas3><unknown>await lb4Application.restServer.getApiSpec()
// Create GraphQl Schema from OpenApiSpec
const {schema} = await createGraphQLSchema(oas, {
strict: false,
viewer: true,
baseUrl: url,
headers: {
'X-Origin': 'GraphQL'
},
createSubscriptionsFromCallbacks: true,
customResolvers: {
"lb4-title": {
"your-path":{
patch: (obj, args, context, info) => {
const num = Math.floor(Math.random() * 10);
pubsub.publish("something", { yourMethodName: {count: num} }).catch((err: any) => {
console.log(err)
})
return {count: 1}
}
}
}
},
customSubscriptionResolvers: {
"lb4-title" : {
"yourMethodName": {
post: {
subscribe: () => pubsub.asyncIterator("something"),
resolve: (obj: any, args: any, context, info) => {
console.log(obj, 'obj')
}
}
}
}
}
})
const app = express();
const server = new ApolloServer({
schema,
plugins: [{
async serverWillStart() {
return {
async drainServer() {
subscriptionServers.close();
}
};
}
}],
})
const subscriptionServers = SubscriptionServer.create(
{
// This is the `schema` we just created.
schema,
// These are imported from `graphql`.
execute,
subscribe,
},
{
server: lb4Application.restServer.httpServer?.server,
path: server.graphqlPath,
//path: server.graphqlPath,
}
);
await server.start();
server.applyMiddleware({ app, path: "/" });
lb4Application.mountExpressRouter('/graphql', app);
return lb4Application
}
Also you will need to define the callbacks object in your controller like so.
#patch('/something-update', {
operationId: 'somethingUpdate',
description: '**GraphQL somethingUpdate**',
callbacks:[
{
yourMethodName: {
post: {
responses: {
'200': {
description: 'response to subscription',
content: {'application/json': {schema: CountSchema}},
}
}
}
},
}
],
responses: {
'200': {
description: 'Something PATCH success count',
content: {'application/json': {schema: CountSchema}},
},
},
})
async updateAll(
#requestBody({
content: {
'application/json': {
schema: getModelSchemaRef(Something, {partial: true}),
},
},
})
something: Something,
#param.where(Something) where?: Where<Something>,
): Promise<Count> {
return this.somethingRepository.updateAll(something, where);
}
And that is it. You can test it out from the GraphQL Playground and play around with the subscriptions.
For the time being, I am fine with defining customResolvers and customSubscriptionResolvers but I'm pretty sure I can automate this two objects from the controllers.
Cheers!
Packages:
redux-observable#2.0.0-rc.2
rxjs latest
universal-rxjs-ajax dev branch
next-redux-wrapper latest
next.js latest
I have a simple Page with getStaticProps:
export const getStaticProps = wrapper.getStaticProps((store) => async (ctx) => {
store.dispatch({ type: 'ADD_DATA' });
// const response = await fetch('https://rickandmortyapi.com/api');
// const data = await response.json();
// store.dispatch({ type: 'SERVER_ACTION', payload: data.characters });
return {
props: {},
};
});
Action 'ADD_DATA' triggers action 'SERVER_ACTION':
export const AddDataEpic: Epic = (action$) =>
action$.pipe(
ofType('ADD_DATA'),
mergeMap((action) =>
request({ url: 'https://rickandmortyapi.com/api' }).pipe(
map((response) => {
return {
type: 'SERVER_ACTION',
payload: response.response.characters,
};
})
)
)
);
Inside the reducer in the case 'SERVER_ACTION': clause I receive the payload:
const server = (state: State = { data: null }, action: AnyAction) => {
switch (action.type) {
case HYDRATE: {
console.log('HYDRATE >', action.payload); // logs out "HYDRATE > { server: { data: null } }"
return {
...state,
...state.server,
...action.payload.server,
};
}
case 'SERVER_ACTION': {
console.log('SERVER_ACTION >', action.payload); // logs out "SERVER_ACTION > https://rickandmortyapi.com/api/character"
return {
...state,
...state.server,
data: action.payload,
};
}
default:
return state;
}
};
But the payload isn't passed to HYDRATE action:
console.log('HYDRATE >', action.payload); // logs out "HYDRATE > { server: { data: null } }"
If I dispatch the 'SERVER_ACTION' action from inside the getStaticProps:
export const getStaticProps = wrapper.getStaticProps((store) => async (ctx) => {
// store.dispatch({ type: 'ADD_DATA' });
const response = await fetch('https://rickandmortyapi.com/api');
const data = await response.json();
store.dispatch({ type: 'SERVER_ACTION', payload: data.characters });
return {
props: {},
};
});
The HYDRATE action inside the reducer receive the payload:
HYDRATE > { server: { data: 'https://rickandmortyapi.com/api/character' } }
I don't understand what's wrong with my code.
May it be a bug in one of the libraries? Or is it a mistake in my code?
If anyone has any suggestions, PLEASE
#PYTHON DEVELOPER999 It might be due to the latest update on next-redux-wrapper, there are few migration steps =>
https://github.com/kirill-konshin/next-redux-wrapper#upgrade-from-6x-to-7x
I'm working at a React app and I need to loop inside an array containing objects with this structure:
const servers = [
{
name: "Server A",
url: "https://server-one.com/version",
accessToken: "yJ0eXAiOiJKV1QiLCyJ0eXAiOiJKV1QiLCyJ0eXAiOiJKV1QiLC",
subVersions: [
{
name: "Subversion A1",
ip: "https://10.4.20/version",
accessToken: "yJ0eXAiOiJKV1QiLCyJ0eXAiOiJKV1QiLCyJ0eXAiOiJKV1QiLC"
},
{
name: "Subversion A2",
ip: "https://10.4.20/v1/version",
accessToken: "yJ0eXAiOiJKV1QiLCyJ0eXAiOiJKV1QiLCyJ0eXAiOiJKV1QiLC"
}
]
},
// ... more servers obj with the same structure
]
and I need to fetch information about the server versions via api calls to the url (or ip) and return an array of objects that looks like this:
[
{
name: "Server A",
version: "1.0.1",
subVersions: [
{
name: "Subversion A1",
version: "1.0.0"
},
{
name: "Subversion A2",
version: "1.0.0"
},
]
}
]
I'm doing is the following: the fetch() method will call fetchVersion() (which returns the main server version), and then it maps inside all the subVersions to fetch them too.
I'm struggling to get the result.data of the subVersions fetch out of that nested map you can see below.
I've tried to:
return the data at every iteration
pushing the data inside an array and try to return it at the end of the iterations
returning the array of data or returning a new Promise that resolves the array of data
But nothing. I can see the right data at the most nested map, but outside I either get a
Promise { <pending> } array or an empty one.
Sorry if the code looks messy, I hope it makes sense.
const fetchVersion = server =>
axios
.get(server.url, {
headers: {
Authorization: `Bearer ${server.accessToken}`,
"Content-Type": "application/json"
},
timeout: 30000
})
.then(result => new Promise(resolve => resolve(result.data)));
const fetchSubVersion = subVersion =>
axios
.get(subVersion.ip, {
headers: {
Authorization: `Bearer ${subVersion.accessToken}`,
"Content-Type": "application/json"
},
timeout: 30000
})
.then(result => new Promise(resolve => resolve(result.data)));
Class Servers {
constructor(servers = []) {
this.servers = servers ;
}
fetch() {
// ==== this map below is the problematic part =====
const subVersions = this.servers.map(server => {
var subVersArr = server.subVersions.map(
async server.subVersions.map(subVersion =>
await fetchSubVersions(subVersion)
.catch(() => ({ data: {} }))
.then(result => new Promise(resolve => resolve(result.data)));
});
})
);
return Promise.all(subVersArr)
.catch(() => ({ data: {} }))
.then(data => {
console.log("data", data); // <- I see the data here correctly
return data;
});
};
// ======= till here ============
const fetches = this.servers.map(server =>
fetchVersion(server)
.catch(() => ({ data: {} }))
.then(result => {
console.log("subVersions", subVersions(server)); <- but not here
return {
name: server.name,
versions: result.data,
subVersions: subVersions(server), // should contain the result of the
problematic map above
}
}))
);
return Promise.all(fetches);
}
Thanks for the help!!
How are you calling your fetch function? You should await it wherever you are calling it.
Like this:
async dummyFunction() {
await fetch();
}
I finally figured it out. What I didn't have clear is that then() returns a promise itself, so all I had to just do subVersion: await subVersions(server) and the data is there.
This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
I have gone through this blog followed the instructions in the blog post http://graphql.org/blog/rest-api-graphql-wrapper/
to create a graphQL endpoint over my own REST API. If I log the calls in the console I can see the correct response getting generated, but the data is always NULL in GraphiQL IDE. What could be the reason?
Here is my code:
import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
} from 'graphql'
import fetch from 'node-fetch'
const BASE_URL = 'http://localhost/my.test.web/api/v1/customer/91/reservation'
const ReservationType = new GraphQLObjectType({
name: 'Reservation',
description: 'This is reservation details',
fields: () => ({
id: {type: GraphQLString},
confirmationNumber: {
type: GraphQLString,
resolve: (reservation) => reservation.confirmationNumber
},
status: {
type: GraphQLString,
resolve: (reservation) => reservation.status
}
})
});
const QueryType = new GraphQLObjectType(
{
name: "query",
description: "This is query by Id",
fields: () => ({
reservation: {
type: ReservationType,
args: {
id: {type: GraphQLString}
},
resolve: (root, args) => {
var url = BASE_URL+ '/' + args.id;
console.log(url);
var options = {
headers: {
'Accept': 'application/json',
'Accept-Language':'en-US'
}
};
fetch(url,options)
.then(function(res) {
return res.json();
}).then(function(json) {
console.log(json);
return json;
});
}
}
}
)
});
export default new GraphQLSchema(
{
query: QueryType,
}
)
When I run this using graphiQL and express, I can see that the log is correctly generated by this part of the code -
.then(function(json) {
console.log(json);
return json;
}
But in the GraphiQL UI the data is null
GraphiQL IDE query screenshot
Finally I was able to find the cause - It is the syntax and not the JSON returned. Notice the "," at the end of each block and also removed the wrapper around the resolve:
The QueryType should be defined as follows and it works like a charm
const QueryType = new GraphQLObjectType({
name: "query",
description: "This is person query by Id",
fields: () => ({
person: {
type: PersonType,
args: {
id: { type: GraphQLString },
},
resolve: (root, args) =>
fetch(BASE_URL +'/people/' +args.id)
.then(function(res) {
return res.json()
})
.then(function(json) {
console.log(json)
return json
}),
},
}),
});