diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java index 0635d78e55a2..4debf1e53a31 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java @@ -438,6 +438,14 @@ public void setXmlRpcUrl(String xmlRpcUrl) { } public String getWpApiRestUrl() { + // WP.com simple sites don't have a stored wpApiRestUrl (the WP.com REST API + // response never sets it, and no other code path populates it for these sites). + // Return the public-api proxy URL so all callers get the correct endpoint + // without needing site-type checks at every call site. + if (isWPComSimpleSite()) { + return "https://public-api.wordpress.com/wp/v2/sites/" + + mSiteId; + } return mWpApiRestUrl; } @@ -926,6 +934,10 @@ public boolean hasDiskSpaceQuotaInformation() { return mSpaceAllowed > 0; } + public boolean isWPComSimpleSite() { + return isWPCom() && !isWPComAtomic(); + } + public boolean isWPComAtomic() { return mIsWPComAtomic; } diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt index 3293117cc6f9..cf3f67009245 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/rs/WpApiClientProvider.kt @@ -16,9 +16,11 @@ import uniffi.wp_api.CookiesNonceAuthenticationProvider import uniffi.wp_api.WpAppNotifier import uniffi.wp_api.WpAuthentication import uniffi.wp_api.WpAuthenticationProvider +import uniffi.wp_api.ParsedUrl import uniffi.wp_api.WpComBaseUrl import uniffi.wp_api.WpComDotOrgApiUrlResolver as WpComUrlResolver // checkstyle ignore import uniffi.wp_api.WpDynamicAuthenticationProvider +import uniffi.wp_api.WpOrgSiteApiUrlResolver import java.net.URL import javax.inject.Inject import javax.inject.Named @@ -56,7 +58,8 @@ class WpApiClientProvider @Inject constructor( site: SiteModel, uploadListener: WpRequestExecutor.UploadListener? = null ): WpApiClient = when { - site.isWPCom -> getWpComApiClient(site) + site.isWPCom || site.isUsingWpComRestApi -> + getWpComApiClient(site) // Skip caching when an upload listener is provided — // upload flows need a dedicated client with progress // callbacks. @@ -76,8 +79,12 @@ class WpApiClientProvider @Inject constructor( username = site.apiRestUsernamePlain, password = site.apiRestPasswordPlain, ) + + val urlResolver = + WpOrgSiteApiUrlResolver(ParsedUrl.parse(site.buildUrl())) + return WpApiClient( - wpOrgSiteApiRootUrl = URL(site.buildUrl()), + apiUrlResolver = urlResolver, authProvider = authProvider, requestExecutor = WpRequestExecutor( interceptors = interceptors.toList(), diff --git a/libs/fluxc/src/test/java/org/wordpress/android/fluxc/model/site/SiteModelTest.kt b/libs/fluxc/src/test/java/org/wordpress/android/fluxc/model/site/SiteModelTest.kt index f530565f411c..ef1cba2c4e81 100644 --- a/libs/fluxc/src/test/java/org/wordpress/android/fluxc/model/site/SiteModelTest.kt +++ b/libs/fluxc/src/test/java/org/wordpress/android/fluxc/model/site/SiteModelTest.kt @@ -3,7 +3,9 @@ package org.wordpress.android.fluxc.model.site import org.junit.Test import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.fluxc.site.SiteUtils +import kotlin.test.assertEquals import kotlin.test.assertFalse +import kotlin.test.assertNull import kotlin.test.assertTrue class SiteModelTest { @@ -157,6 +159,100 @@ class SiteModelTest { assertFalse(site.supportsSharing()) } + /* isWPComSimpleSite */ + @Test + fun `wpcom non-atomic site is a simple site`() { + val site = SiteUtils.generateWPComSite() + site.setIsWPComAtomic(false) + + assertTrue(site.isWPComSimpleSite) + } + + @Test + fun `wpcom atomic site is not a simple site`() { + val site = SiteUtils.generateWPComSite() + site.setIsWPComAtomic(true) + + assertFalse(site.isWPComSimpleSite) + } + + @Test + fun `self-hosted site is not a simple site`() { + val site = SiteUtils.generateSelfHostedNonJPSite() + + assertFalse(site.isWPComSimpleSite) + } + + @Test + fun `jetpack site is not a simple site`() { + val site = SiteUtils.generateJetpackSiteOverRestOnly() + + assertFalse(site.isWPComSimpleSite) + } + + /* getWpApiRestUrl — proxy URL for simple sites */ + @Test + fun `atomic site returns stored wpApiRestUrl`() { + val site = SiteUtils.generateWPComSite() + site.setIsWPComAtomic(true) + site.wpApiRestUrl = "https://atomic.example.com/wp-json/" + + assertEquals("https://atomic.example.com/wp-json/", site.wpApiRestUrl) + } + + @Test + fun `self-hosted site with no wpApiRestUrl returns null`() { + val site = SiteUtils.generateSelfHostedNonJPSite() + + assertNull(site.wpApiRestUrl) + } + + @Test + fun `atomic site with no stored wpApiRestUrl returns null`() { + val site = SiteUtils.generateWPComSite() + site.setIsWPComAtomic(true) + + assertNull(site.wpApiRestUrl) + } + + @Test + fun `simple site proxy URL uses wpcom siteId not local id`() { + val site = SiteUtils.generateWPComSite() + site.setIsWPComAtomic(false) + site.siteId = 99887766 + site.id = 42 + + assertEquals( + "https://public-api.wordpress.com/wp/v2/sites/99887766", + site.wpApiRestUrl + ) + } + + @Test + fun `simple site proxy URL overrides stored wpApiRestUrl`() { + val site = SiteUtils.generateWPComSite() + site.setIsWPComAtomic(false) + site.wpApiRestUrl = "https://should-be-ignored.example.com/wp-json/" + + assertEquals( + "https://public-api.wordpress.com/wp/v2/sites/${site.siteId}", + site.wpApiRestUrl + ) + } + + @Test + fun `jetpack REST site returns stored url not proxy`() { + val site = SiteUtils.generateJetpackSiteOverRestOnly() + site.wpApiRestUrl = "https://jetpack.example.com/wp-json/" + + assertTrue(site.isUsingWpComRestApi) + assertFalse(site.isWPComSimpleSite) + assertEquals( + "https://jetpack.example.com/wp-json/", + site.wpApiRestUrl + ) + } + private fun SiteModel.setPublicizeSupport(enablePublicizeSupport: Boolean) { this.hasCapabilityPublishPosts = enablePublicizeSupport if (isJetpackConnected) {