Repository navigation
Conversation
…nse extras
- Add AuthConfig with Basic/Bearer/ApiKey(in Header or Query) support
- Extend RequestContext with BodyType(raw/json/xml/form-urlencoded/binary/form-data),
binaryBody and queryParams; fluent Builder methods for each
- Enhance ResponseResult with cookies, json() and contentType()
- Apply auth/body/query params in NetworkRequest pipeline
- GUI: auth settings dialog (incl. ApiKey), binary body page, response Cookies tab,
route UI through RequestContextBuilder
- Tests: AuthTests/BodyTypeTests suites + GUI buildRequestContext/auth/cookies cases
- Fix greedy hex-escape bugs in test fixtures ('\x00DEF' -> C7744, '\x00data' -> 0x00DA)
…y, cleanup and test.bat - Add NetworkRequestTool::applyBodySyntaxHighlighting to colorize raw JSON/XML request bodies (reuses JsonSyntaxHighlighter/XmlSyntaxHighlighter); clears the 4 TODO placeholders in onBodyTypeChanged/onRawTypeChanged - Add RequestContextBuilder::bodyFormData(files, kvPairs) so BodyType::FormData has a symmetric builder; add testBodyFormDataBuilder (BuilderTests) - Section F cleanup: merge duplicate cmb_body_type slot onBodyTypeComboChanged into onBodyTypeChanged (also fixes cmb_raw_type left enabled after binary), and remove the duplicate table_headers cellChanged lambda in the constructor - Add scripts/test.bat (Windows counterpart of test_local.sh): Qt/VS auto-detect, configure + build + ctest, with /clean /nobuild /debug /help and ctest exit code propagated
…/ Postman v2.1)
New files:
- include/authconfig.h: OAuth2Config with 4 grant types + bearer token header
- include/environment.h, source/environment.cpp: env var substitution
({{var}} in url/headers/body/queryParams/auth fields)
- include/oauth2tokencache.h, source/oauth2tokencache.cpp: Q_GLOBAL_STATIC
singleton token cache with expiry
- include/collectionmodel.h, source/collectionmodel.cpp: in-memory Collection
tree (folders + requests) with JSON serde, findById, add/remove
- include/postmanconverter.h, source/postmanconverter.cpp: Postman v2.1
bidirectional converter (auth round-trip, nested folders, request mapping)
- test/test_environment.*, test/test_collection.*, test/test_postman.*,
test/main_collection.cpp: BuilderTests env cases + CollectionTests
Modified:
- include/requestcontext.h: BodyType::FormData + bodyFormData() builder
- source/CMakeLists.txt, test/CMakeLists.txt: added new sources
- scripts/test.bat: Windows test runner (walk-up repo root, goto VS detect,
no EnableDelayedExpansion, echo brackets avoided)
Fixes across 4 compile rounds: struct order, member/method name collision,
Q_GLOBAL_STATIC access, QJsonArray::reserve, Qt5.15 QString::replace API,
missing QJsonArray/QJsonObject includes, Postman import empty-id collision.
All 7 test suites pass.
Pipeline (B.2):
- source/networkrequest.cpp: wire applyEnvironment() into setRequestContext()
after m_upContext = move and before m_url = QUrl, so {{var}} placeholders
are resolved before the URL/headers/body/query/auth are finalized.
EnvironmentStore (B.3):
- include/environmentstore.h, source/environmentstore.cpp: multi-environment
manager with JSON persistence ({active, environments[{name, variables}]}).
NETWORK_EXPORT, no UI dependency.
- source/CMakeLists.txt: add environmentstore.cpp + .h
GUI (B.4):
- networkrequesttool.h: EnvironmentStore m_envStore, QComboBox/PushButton
members, onEnvironmentChanged/onManageEnvironments slots, helpers.
- networkrequesttool.cpp:
- initializeUI(): inject cmb_environment + btn_manage_env into request toolbar
- buildRequestContext(): append .environment(m_envStore.activeVariables())
- loadEnvironments(): load from environments.json, create default 'Dev' on
first run (host=localhost, port=8080)
- onManageEnvironments(): full dialog with QListWidget env picker +
QTableWidget variable editor + Add/Remove + JSON persistence
UiTests:
- test_qtrequester.h/.cpp: test_envDropdownSwitch verifies combo exists,
No Environment yields empty map, Dev selection populates activeVariables,
buildRequestContext carries the env map.
All 7 test suites green.
R1 — applyAuthConfig OAuth2 case:
- source/networkrequest.cpp: fold AuthType::OAuth2 into Basic/Bearer group
so the fetched access_token is written to the Authorization header.
Refactor start() -> performSend():
- source/networkcommonrequest.h: add #include <functional>, private methods
performSend() and fetchOAuth2Token(onReady).
- source/networkcommonrequest.cpp: extract send block (L98-243) into
performSend(). start() calls fetchOAuth2Token for OAuth2, else directly
calls performSend().
fetchOAuth2Token async token retrieval:
- Cache key via OAuth2TokenCache::makeKey(). Synchronous fast path on cache
hit (find() + isValid()). Miss -> POST to tokenUrl via thread-affine NAM
(NetworkRequestManager::acquireThreadNam()). Parse JSON {access_token,
refresh_token, expires_in}, store to OAuth2TokenCache::instance().store().
Errors reported via setError() + emit response(ToFailedResult()).
401 auto-refresh:
- m_bOAuthRefreshed flag moved from NetworkCommonRequest to base class
NetworkRequest (source/networkrequest.h). Reset in setRequestContext().
- handleFailure() in base class gains OAuth2 401 branch: after tryRetry(),
before redirect. On 401 + OAuth2 + !refreshed + refreshToken available:
set refreshed=true, swap grant to RefreshToken, cleanup + restart().
Second 401 skips refresh (guard), emits failure.
GUI OAuth2 settings (A.4):
- RequestSettings gains 8 OAuth2 fields (grantType/clientId/clientSecret/
scopes/tokenUrl/username/password/refreshToken).
- onSettingsClicked(): add 'OAuth2' to authTypeCombo, add OAuth2 controls
(grant combo + 7 QLineEdits), show/hide by grant type (Password shows
user/pass, Refresh Token shows refresh field).
- buildAuthConfig(): new OAuth2 branch builds OAuth2Config from settings
and returns AuthConfig::oauth2(cfg).
All 7 test suites green.
GUI-only enhancement — inject a compact toolbar into the response body tab: Search (QLineEdit + prev/next buttons): - onResponseSearchChanged: re-search on every keystroke - doResponseSearch: QTextDocument::find() to collect all matches, highlight with QTextEdit::ExtraSelection (yellow for all, orange for current hit) - navigateSearchHit(): wrap-around prev/next with scroll-to-hit Copy: QApplication::clipboard()->setText(response body) Save: QFileDialog::getSaveFileName + QFile::write(response body) Pretty/Raw toggle: re-format JSON with QJsonDocument::Indented (pretty) or show raw m_lastResponseBody. Non-JSON responses ignore the toggle. onResponse() now stores m_lastResponseBody + m_isResponseJson. Response toolbar injected at index 1 in verticalLayout_response_body (after m_labelResponseInfo, mirroring existing injection pattern). All 7 test suites green.
R2 — auth serialize/deserialize: - saveToDisk(): serialize all auth fields (type/Basic/Bearer/ApiKey/OAuth2) alongside method/url/body/headers so authenticated requests survive save/load and Postman round-trips. - loadRequestFromJson(): new reusable method extracts form population from loadFromDisk; restores auth fields into m_settings. loadFromDisk() is now a thin file-I/O wrapper calling loadRequestFromJson. D.1 — loadFromDisk refactor: - Dead loadFromDisk() refactored into loadRequestFromJson(const QJsonObject&), reusable by collection-click (D.3) and Postman import (E.2). - loadFromDisk() = open file + parse JSON + call loadRequestFromJson. D.2-D.4 — Collection tree panel: - buildCollectionPanel(): inject QTreeWidget + toolbar (+Coll/+Folder/+Req/ Import/Export) into left panel layout above history list. - loadCollection()/saveCollection(): persist to collection.json via Collection::load/save. - populateCollectionTree(): rebuild tree from Collection model (folders have folder icon, requests have file icon). - onNewCollection(): create a named collection. - onAddCollectionFolder(): add folder under selected node or root. - onAddCollectionRequest(): snapshot current form (url/method/body/headers/ auth) as a collection request node. - onCollectionItemClicked(): load request into form via loadRequestFromJson. - onImportPostman(): QFileDialog -> PostmanConverter::fromPostmanV21. - onExportPostman(): PostmanConverter::toPostmanV21 -> QFileDialog write. All 7 test suites green.
Tests: - HttpTestServer: add /oauth/token endpoint supporting client_credentials, password, and refresh_token grants with proper validation. - AuthTests: 5 new OAuth2 integration tests (client_credentials, cache hit, password grant, refresh_token, tokenUrl-missing rejection). - UiTests: testSaveAndLoadDiskWithAuth (R2 auth serialisation round-trip for Bearer + OAuth2 fields), testResponseSearch (search highlighting + prev/next navigation). Bug fix: - include/requestcontext.h: add missing RequestContextBuilder::authOAuth2() method (A.2 from original plan, missed during M0). Docs: - Changelog: v2.3.0 entry covering all M0-M4 features. - README.zh-CN.md: add OAuth2, environments, response toolbar, collections, Postman v2.1 to feature list. - AGENTS.md: update directory map (16 public headers, 7 test suites, 39+ source files). All 7 test suites green.
1. Fix abort empty stub: onAbortTask() now stores taskId from NetworkReply
and calls stopRequest(); onResponse() clears taskId on completion.
2. Fix auth env var expansion: applyAuthHeader() now resolves {{var}}
placeholders in Basic/Bearer/ApiKey credentials before writing headers.
3. Fix silent auth fallback: onSendRequest() now warns via QMessageBox when
a non-None auth type is selected but required credentials are empty.
Tests updated:
- testAbortRunningRequest: real abort flow with mock server (was QSKIP)
- testApplyAuthHeader: added {{token}} env expansion case
- testAuthEmptyCredentialFallback: added warning dialog auto-dismiss case
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes three defects discovered during comprehensive UI interaction testing:
1. Abort empty stub -> real implementation
onAbortTask()was completely empty. Now:m_currentTaskIdtracks the running request viaNetworkReply::task()->idonAbortTask()callsstopRequest(taskId)and clears the idonResponse()clears taskId on normal completion2. Auth credential env var expansion
applyAuthHeader()now resolves{{var}}placeholders in auth credentials (Basic username/password, Bearer token, ApiKey key/value) before writing the Authorization header.3. Silent auth credential fallback -> user warning
When a non-None auth type is selected but required credentials are empty,
onSendRequest()now shows aQMessageBox::warningso the user knows the request will be sent without authentication.Test changes
testAbortRunningRequest: real abort flow with mock server (wasQSKIP)testApplyAuthHeader: added{{token}}env expansion casetestAuthEmptyCredentialFallback: added warning dialog auto-dismiss caseTest results