Open NghiaTranUIT opened 4 years ago
@NghiaTranUIT Loving Proxyman. I've already recommended it to a couple different people.
I'm curious about this issue. Would it allow Map Local and Map Remote for GraphQL queries and mutations? This is something I've wanted for a long time in Charles, and even sent in feature requests twice for.
In other words, I'd like to map requests to /graphql
differently based on the request body. Map Local/Remote are based on path, but since all GraphQL requests typically go to the same path with a different body (operationName
, variables
, and query
) it's impossible to use Map Local/Remote for GraphQL right now, as far as I know. Would that come along with this story or should I file a different issue?
Thank you!!
@atdrago Thank you for your kind words. Since I've just released the Proxyman v2 - which is rewritten with Swift- NIO (https://github.com/ProxymanApp/Proxyman/releases/tag/2.0.0), I totally free to push up new features.
GraphQL is what I'm looking for since there are not many tools that support debugging GraphQL.
You're right. At the moment, Map Local/Remote is based on the path, so it's impossible to map the content of the GraphQL. On the other hand, mapping base on operationName, variables, and query
seems easier to implement.
I'm planning to support this soon 👍
Thanks for your quick response!
This is so exciting to hear! I actually saw v2 come through. I updated and it inspired me to come check if anyone has requested GraphQL support yet. Keep up the great work!!!
@atdrago I want to map local one of the graphQL queries.
One of my solution of map local graphQL queries are appending the query name into the URL. So domain.com/api/graphql
changed to domain.com/api/graphql?gqlquery=MyQuery
. I plan to modify the URL using the script tool.
Once the script tool has change the request url, I can then map local domain.com/api/graphql?gqlquery=MyQuery
to change the response of only that query.
However, when I try this solution, I found that the map local is not applied. Here are some screenshots:
An interesting fact, that if I choose repeat the request, the response is the local response I have in map local. When repeat the request, the URL is already with the gqlquery=MyQuery
, that's why map local works.
It seems that map local only recognize the original url before it changed by the script tool.
It would be really cool if this works.
Hey @nuynait, at the moment, the Scripting will run after the Map Local. Therefore, it's a expected behavior.
To support GraphQL, I suggest that you can use
// /Users/<username>/Library/Application Support/com.proxyman.NSProxy/users/B02D96D5.default_message_32E64A5B.json
const file = require("@users/B02D96D5.default_message_32E64A5B.json");
function onRequest(context, url, request) {
// 1. Extract the queryName from the request var queryName = request.body.query.match(/\S+/gi)[1].split('(').shift();
// 2. Save to sharedState sharedState.queryName = queryName
// Done return request; }
function onResponse(context, url, request, response) {
// 3. Check if it's the request we need to map if (sharedState.queryName == "user") {
// 4. Import the local file by Action Button -> Import
// Get the local JSON file and set it as a body (like Map Local)
response.headers["Content-Type"] = "application/json";
response.body = file;
}
// Done return response; }
The above script will achieve the same result that you're trying 👍
Meanwhile, it's correct that the Scripting Tool should be executed before other tools, such as Map Local, Remote, ...
I will revisit the logic and improve it 👍
Hi @NghiaTranUIT Thanks for the quick and detailed reply. Thanks for all the tips on how to set up scripting so that I can map to the local response for GQL query. That's really helpful to someone who is new to Proxyman like me.
I would also be very interesting to know when you will be improving the logic since using Map Local tool instead of the scripting would be a much clean and interesting solution instead of doing the map in the scripting tool.
Ultimately, I will find a way to support GraphQL Rule, so we can define which query in the GraphQL body 👍
For now, I would suggest that using the Scripting tool 😄
Hi @NghiaTranUIT. I too am trying to figure out how to map local on graphql when there are multiple calls made, but only one endpoint. I used your script above, but am still not seeing my local file updating when I pull to refresh on the device when the script is running. If I repeat the request, an new request is displayed in the Proxyman and the response is updated with the file I want to replace it with from the script, but the changes do not display on the device. Could you help me figure out what I'm missing? Here is my script:
// /Users/teresa.castle/Library/Application Support/com.proxyman.NSProxy/users/AE397ECE.homepage_article.json const file = require("@users/AE397ECE.homepage_article.json"); // replace intercepted response with this file
function onRequest(context, url, request) { var operationName = request.body.query.match(/\S+/gi)[1].split('(').shift(); request.queries["gqlquery"]=operationName // adds operationName parameter sharedState.operationName = operationName console.log(sharedState.operationName) return request; }
function onResponse(context, url, request, response) {
console.log(sharedState.operationName)
if (sharedState.operationName == "appHomeScreen") {
response.headers["Content-Type"] = "application/json";
response.body = file; // should replace with the file from the const file = require(....) from above
}
return response;
}
It seems correct @TeresaCastle, if you could not see the change, let add some console.log()
to make sure it's correct.
For instance,
console.log(sharedState.operationName)
-> When making a request, do you see the log is appHomeScreen
?console.log(sharedState.operationName)
from onResponse() function?It looks like the expression if (sharedState.operationName == "appHomeScreen")
is false, so it the JSON file doesn't replace the Response Body
I suggest adding some console.log and debug to see if what is wrong 👍
I was seeing appHomeScreen on all of my console.log(). I think I see what is wrong. I have "appHomeScreen" and the console.log() is returning "AppHomeScreen". I've updated the script and it looks like it is working as expected.
I appreciate you taking the time to respond. I'm a manual tester with little scripting experience, but after reading your response, it took me 5 seconds to figure out what was wrong with what I had been staring at for 8 hours, lol.
Thanks so much!!!
Glad to know that it works for you 🎉
Just a friendly reminder: From build 2.20.0, we can quickly see the Query name of GraphQL requests on the main table.
It's super easier to distinguish graphQL request since the URLs are the same 🎉
This is great and will definitely help identify the current GraphQL operation! Thank you @NghiaTranUIT !
Regarding my original comment wrt mapping local, we now add ?opname=${operationName}
to the query string of our /graphql
requests (as @nuynait and others have suggested). It solves the Map Local problem and makes Network logs way easier to read
Glad to know it helps you 😊
Hey guys, I'm working on this feature (#840), which allows us to define a rule by QueryName from GraphQL's Request Body. Therefore, you can use any debugging tools with GraphQL too 😄
Good news to @atdrago @TeresaCastle @nuynait @Elecweb @erickva and anyone who would like to use Breakpoint, Map Local with GraphQL request 🙌
If you guys find any problems/bugs, please report here. I appreciate it ❤️
Debugging with GraphQL feature is available on the latest build (2.27.0). Please update it 😄
Thanks all 🙇
@NghiaTranUIT This is incredible news. I am no longer working on a Project with GraphQL, but it will happen again soon. Great effort! It will be a life saver. ❤️
Does this work with mutations as well or just queries?
It works with mutation too @cameroncooke
For instance, the QueryName is ViewerNotificationsLastSeenUpdate
in this graphQL Body.
{
"query": "mutation ViewerNotificationsLastSeenUpdate{response:viewerNotificationsLastSeenUpdate(input:{}){node{id notificationFeedItemsUnreadCount notificationFeedLastSeenAt __typename}__typename}}"
}
🐶 Brief
Currently, it's super difficult to see the content of GraphQL requests even though in pretty JSON Previewer. The original discussion at https://www.reddit.com/r/macapps/comments/f7u7bb/proxyman_modern_and_delightful_web_debugging/fihjlwq?utm_source=share&utm_medium=web2x
Let see how we support it 🙌
👑 Criteria