Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove references to API and document proxy steps. #234

Merged
merged 9 commits into from
May 28, 2024
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
93 changes: 93 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,96 @@ npm run lint
1. Install the [AEM CLI](https://github.com/adobe/aem-cli): `npm install -g @adobe/aem-cli`
1. Start AEM Proxy: `aem up` (opens your browser at `http://localhost:3000`)
1. Open the `{repo}` directory in your favorite IDE and start coding :)


### Local Proxy for APIs
There are numerous APIs that this site relies on, including but not limited to:

* Account (login, profile, etc)
* Blog
* Properties (search, listing, etc)
* Agent (details, search)
* Suggestions

All of these APIs are hosted on an AMS system. To make use of them locally, a proxy is needed.

There are two ways to set up the local proxy:

* [Real Domain Proxy](#real-domain-proxy)
* Less configuration, but must be aware when proxy is/isn't running.
* [Local Proxy to Remote](#local-proxy-to-remote)
* More configuration, but explicit domain for proxy - clear delineation of live and proxied traffic.

Either way, you need to download and install a local proxy. These instructions use [Proxyman](https://proxyman.io/download). Once you download and install Proxyman, you will need to also install the Proxyman CA certs. These are needed to be able to route the secure traffic.


#### Real Domain Proxy

In this setup, the proxy is configured to route non-API traffic on the Staging domain to your local computer. So all requests _except_ the APIs will go the local host. The API calls will remain routed to the Stage domain.

1. Create a new Allow List entry:
* _Tools_ => _Allow List_
* Name: `BHHS Stage`
* Rule: `https://stage.commonmoves.com*`
* Any, Use Wildcard
* Include all subpaths of this URL: Checked

1. Create a new Map Remote Entry:
* _Tools_ => _Map Remote_
* Matching Rule:
* Name: `BHHS API`
* Rule: `https://stage.commonmoves.com(?!(/bin|/content)).*`
* Any, Use Regex
* Include all subpaths of this URL: Checked
* Map To:
* Protocol: `http`
* Host: localhost
* Port: 3000



#### Local Proxy to Remote

This setup uses a locally resolved domain, which will Proxyman will use to route the traffic. All non-API traffic will route to localhost, all API traffic will go to the Stage domain.

1. Add an entry to `/etc/maps`:
Proxyman won't proxy localhost, so a custom domain is required. Add the following (if you already have a host entry for 127.0.0.1, simply add the new domain)
> 127.0.0.1 proxyman.debug

2. Create a self-signed cert. This is necessary for the AEM Cli to so that cookies can be persisted. It really doesn't matter what you answer for the questions. Just make sure you do not create the certs in the code repo, or add them to Git.

(`/some/path` is used as a reference here, find an appropriate spot on your local computer)

```
$ cd /some/path
$ openssl req -x509 -sha256 -nodes -newkey rsa:2048 -days 365 -keyout localhost.key -out localhost.crt
```

3. Create a new Allow List entry:
* _Tools_ => _Allow List_
* Name: *Localhost*
* Matching Rule `https:\/\/proxyman\.debug:\d+.*`
* Any, Use Regex
* Include all subpaths of this URL: checked

4. Create a new Map Remote Entry:
* _Tools_ => _Map Remote_
* Matching Rule
* Name: *BHHS API*
* Rule: `https://proxyman.debug:\d+(/bin|/content).*`
* Any, Use Regex
* Include all subpaths of this URL: checked
* Map To
* Protocol: `https`
* Host: `stage.commonmoves.com`
* Port: `443`

5. Staring the AEM local proxy requires also passing in the Cert info, to run using https:

(`/some/path` is the same place you previously created the cert)

```
% aem up --tls-cert /some/path/localhost.crt --tls-key /some/path/localhost.key
```

To view Proxied site use: https://proxyman.debug:3000/
7 changes: 2 additions & 5 deletions blocks/blog-details/blog-details.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
const urlParams = new URLSearchParams(window.location.search);
export const API_HOST = urlParams.get('env') === 'stage' ? 'https://ignite-staging.bhhs.com' : 'https://www.bhhs.com';

function getBlogDetailsPath() {
const url = window.location.pathname;
const startIndex = url.indexOf('/blog/blog-detail/') + '/blog/blog-detail/'.length;
return url.substring(startIndex);
}

function buildApiPath() {
return `${API_HOST}/blog/blog-detail/jcr:content/${getBlogDetailsPath()}.json`;
return `/blog/blog-detail/jcr:content/${getBlogDetailsPath()}.json`;
}

function buildImageUrl(path) {
return `${API_HOST}${path}`;
return `${path}`;
}

/**
Expand Down
17 changes: 5 additions & 12 deletions blocks/blog-listing/blog-listing.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import {
readBlockConfig,
} from '../../scripts/aem.js';

const urlParams = new URLSearchParams(window.location.search);
export const API_HOST = urlParams.get('env') === 'stage' ? 'https://ignite-staging.bhhs.com' : 'https://www.bhhs.com';

const DEFAULT_SCROLL_INTERVAL_MS = 6000;
const DEFAULT_DESCRIPTION_LENGTH = 141;
const category = window.location.pathname.split('/').filter(Boolean)[1] ?? '';
Expand All @@ -18,9 +15,9 @@ let scrollInterval;
function buildApiPath(offset, count) {
let url;
if (category === '') {
url = `${API_HOST}/content/bhhs-franchisee/ma312/en/us/blog/jcr:content/root/blog_home.blogs.offset_${offset}.count_${count}.json`;
url = `/content/bhhs-franchisee/ma312/en/us/blog/_jcr_content/root/blog_home.blogs.offset_${offset}.count_${count}.json`;
} else {
url = `${API_HOST}/content/bhhs-franchisee/ma312/en/us/blog/blog-category/jcr:content/root/blog_category.blogCategory.category_${category}.offset_${offset}.count_${count}.json`;
url = `/content/bhhs-franchisee/ma312/en/us/blog/blog-category/_jcr_content/root/blog_category.blogCategory.category_${category}.offset_${offset}.count_${count}.json`;
}
return url;
}
Expand Down Expand Up @@ -49,10 +46,6 @@ function trimDescription(description) {
return `${trimmedDescription.substring(0, DEFAULT_DESCRIPTION_LENGTH)}...`;
}

function buildImageUrl(path) {
return new URL(`${API_HOST}${path}`).href;
}

function prepareBlogArticleUrl(link) {
return link.replace(/\.html$/, '');
}
Expand All @@ -72,9 +65,9 @@ function buildBlogItem(block, data, addClass = false) {
blogContainer.innerHTML = `
<div class="image-content">
<picture>
<source media="(max-width:767px)" srcset="${buildImageUrl(mobileImage)}">
<source media="(min-width:768px) and (max-width:1279px)" srcset="${buildImageUrl(tabletImage)}">
<img src="${buildImageUrl(image)}" class="image" aria-label="${title}" alt="${title}">
<source media="(max-width:767px)" srcset="${mobileImage}">
<source media="(min-width:768px) and (max-width:1279px)" srcset="${tabletImage}">
<img src="${image}" class="image" aria-label="${title}" alt="${title}">
</picture>
</div>
<div class="blog-content">
Expand Down
9 changes: 5 additions & 4 deletions scripts/apis/agent/agent.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
const urlParams = new URLSearchParams(window.location.search);
export const DOMAIN = urlParams.get('env') === 'stage' ? 'ignite-staging.bhhs.com' : 'www.bhhs.com';
const API_URL = `https://${DOMAIN}/bin/bhhs`;
/*
Agent API
*/

/**
* Search for Agents
* @param {SearchParameters} params the parameters
* @return {Promise<Object>}
*/
// eslint-disable-next-line import/prefer-default-export
export async function search(params) {
return new Promise((resolve) => {
const worker = new Worker(`${window.hlx.codeBasePath}/scripts/apis/agent/workers/search.js`);
const url = `${API_URL}/solrAgentSearchServlet?${params.asQueryString()}&_=${Date.now()}`;
const url = `/bin/bhhs/solrAgentSearchServlet?${params.asQueryString()}&_=${Date.now()}`;
worker.onmessage = (e) => resolve(e.data);
worker.postMessage({ url });
});
Expand Down
5 changes: 1 addition & 4 deletions scripts/apis/agent/suggestion.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { DOMAIN } from './agent.js';
import Filter from './Filter.js';

const API_URL = `https://${DOMAIN}/bin/bhhs`;

let suggestionFetchController;

/**
Expand All @@ -18,7 +15,7 @@ export async function getSuggestions(office, keyword) {
suggestionFetchController = new AbortController();
const { signal } = suggestionFetchController;

const endpoint = `${API_URL}/suggesterServlet?search_type=agent&keyword=${keyword}&office_id=${office}&_=${Date.now()}`;
const endpoint = `/bin/bhhs/suggesterServlet?search_type=agent&keyword=${keyword}&office_id=${office}&_=${Date.now()}`;
return fetch(endpoint, { signal })
.then((resp) => {
if (resp.ok) {
Expand Down
8 changes: 0 additions & 8 deletions scripts/apis/creg/creg.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
// TODO: Use Sidekick Plugin for this
import { getMetadata } from '../../aem.js';

const urlParams = new URLSearchParams(window.location.search);
export const DOMAIN = urlParams.get('env') === 'stage' ? 'ignite-staging.bhhs.com' : 'www.bhhs.com';
const CREG_API_URL = `https://${DOMAIN}/bin/bhhs`;

/**
* @typedef {Object} SearchResults
* @property {Array<Object>} properties
Expand All @@ -27,7 +23,6 @@ export async function propertySearch(search) {
const worker = new Worker(`${window.hlx.codeBasePath}/scripts/apis/creg/workers/properties.js`, { type: 'module' });
worker.onmessage = (e) => resolve(e.data);
worker.postMessage({
api: CREG_API_URL,
search,
});
});
Expand All @@ -44,7 +39,6 @@ export async function metadataSearch(search) {
const worker = new Worker(`${window.hlx.codeBasePath}/scripts/apis/creg/workers/metadata.js`, { type: 'module' });
worker.onmessage = (e) => resolve(e.data);
worker.postMessage({
api: CREG_API_URL,
search,
});
});
Expand All @@ -61,7 +55,6 @@ export async function getDetails(...listingIds) {
const worker = new Worker(`${window.hlx.codeBasePath}/scripts/apis/creg/workers/listing.js`, { type: 'module' });
worker.onmessage = (e) => resolve(e.data);
worker.postMessage({
api: CREG_API_URL,
ids: listingIds,
officeId,
});
Expand All @@ -80,7 +73,6 @@ export async function getEconomicDetails(lat, long) {
const worker = new Worker(`${window.hlx.codeBasePath}/scripts/apis/creg/workers/economic.js`, { type: 'module' });
worker.onmessage = (e) => resolve(e.data);
worker.postMessage({
api: CREG_API_URL,
lat,
long,
});
Expand Down
8 changes: 4 additions & 4 deletions scripts/apis/creg/suggestion.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const urlParams = new URLSearchParams(window.location.search);
export const DOMAIN = urlParams.get('env') === 'stage' ? 'ignite-staging.bhhs.com' : 'www.bhhs.com';
const CREG_API_URL = `https://${DOMAIN}/bin/bhhs`;
/*
Suggestion API
*/

let suggestionFetchController;

Expand Down Expand Up @@ -46,7 +46,7 @@ export async function get(keyword, country = undefined) {

const { signal } = suggestionFetchController;

let endpoint = `${CREG_API_URL}/cregSearchSuggesterServlet?Keyword=${keyword}&_=${Date.now()}`;
let endpoint = `/bin/bhhs/cregSearchSuggesterServlet?Keyword=${keyword}&_=${Date.now()}`;
if (country) {
endpoint += `&Country=${country}`;
}
Expand Down
4 changes: 2 additions & 2 deletions scripts/apis/creg/workers/economic.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
* @param {string} event.data.long longitude
*/
onmessage = async (event) => {
const { api, lat, long } = event.data;
const { lat, long } = event.data;
const promises = [];
promises.push(
fetch(`${api}/pdp/socioEconomicDataServlet?latitude=${lat}&longitude=${long}`)
fetch(`/bin/bhhs/pdp/socioEconomicDataServlet?latitude=${lat}&longitude=${long}`)
.then((resp) => (resp.ok ? resp.json() : undefined)),
);

Expand Down
4 changes: 2 additions & 2 deletions scripts/apis/creg/workers/listing.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
* @param {string[]} event.data.ids list of listing ids
*/
onmessage = async (event) => {
const { api, ids, officeId } = event.data;
const { ids, officeId } = event.data;
const promises = [];
ids.forEach((id) => {
promises.push(
fetch(`${api}/CregPropertySearchServlet?SearchType=ListingId&ListingId=${id}${officeId ? `&OfficeCode=${officeId}` : ''}`)
fetch(`/bin/bhhs/CregPropertySearchServlet?SearchType=ListingId&ListingId=${id}${officeId ? `&OfficeCode=${officeId}` : ''}`)
.then((resp) => (resp.ok ? resp.json() : undefined)),
);
});
Expand Down
4 changes: 2 additions & 2 deletions scripts/apis/creg/workers/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import Search from '../search/Search.js';
*
*/
onmessage = async (event) => {
const { api, search } = event.data;
const { search } = event.data;
const results = await Search.fromJSON(search)
.then((s) => {
try {
return fetch(`${api}/CregPropertySearchServlet?${s.asCregURLSearchParameters()}`);
return fetch(`/bin/bhhs/CregPropertySearchServlet?${s.asCregURLSearchParameters()}`);
} catch (error) {
// eslint-disable-next-line no-console
console.log('Failed to fetch properties from API.', error);
Expand Down
4 changes: 2 additions & 2 deletions scripts/apis/creg/workers/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import Search from '../search/Search.js';
* @param {Search} event.data.searches search context
*/
onmessage = async (event) => {
const { api, search } = event.data;
const { search } = event.data;
const results = await Search.fromJSON(search)
.then((s) => {
try {
return fetch(`${api}/CregPropertySearchServlet?${s.asCregURLSearchParameters()}`);
return fetch(`/bin/bhhs/CregPropertySearchServlet?${s.asCregURLSearchParameters()}`);
} catch (error) {
// eslint-disable-next-line no-console
console.log('Failed to fetch properties from API.', error);
Expand Down
18 changes: 7 additions & 11 deletions scripts/apis/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
* API for interacting with the User system.
*/

const urlParams = new URLSearchParams(window.location.search);
export const DOMAIN = urlParams.get('env') === 'stage' ? 'ignite-staging.bhhs.com' : 'www.bhhs.com';
const API_URL = '/bin/bhhs';

/**
* Confirms if user is logged in or not
* @return {boolean}
Expand Down Expand Up @@ -43,7 +39,7 @@ export function getUserDetails() {

async function fetchUserProfile(username) {
const time = new Date().getTime();
const profileResponse = await fetch(`${API_URL}/cregUserProfile?Email=${encodeURIComponent(username)}&_=${time}`);
const profileResponse = await fetch(`/bin/bhhs/cregUserProfile?Email=${encodeURIComponent(username)}&_=${time}`);
const json = profileResponse.json();
return json;
}
Expand All @@ -63,7 +59,7 @@ export function onProfileUpdate(listener) {
/** Make changes to the user profile in session (does not save to the servlet)
* This also triggers any listeners that are registered for profile updates
*
* @param {Object} Updated user profile
* @param {Object} profile the updated user profile
*/
export function updateProfile(profile) {
const userDetails = getUserDetails();
Expand All @@ -80,7 +76,7 @@ export function updateProfile(profile) {
/**
* Attempt to update the user profile. If successful, also update session copy.
* Caller must look at response to see if it was successful, etc.
* @param {Object} Updated user profile
* @param {Object} profile the updated user profile
* @returns response object with status, null if user not logged in
*/
export async function saveProfile(profile) {
Expand All @@ -91,7 +87,7 @@ export async function saveProfile(profile) {
const existingProfile = userDetails.profile;

// Update profile in backend, post object as name/value pairs
const url = `${API_URL}/cregUserProfile`;
const url = '/bin/bhhs/cregUserProfile';
const postBody = {
FirstName: profile.firstName,
LastName: profile.lastName,
Expand Down Expand Up @@ -139,7 +135,7 @@ export async function requestPasswordReset() {
return null;
}

const url = `${API_URL}/cregForgotPasswordtServlet`;
const url = '/bin/bhhs/cregForgotPasswordtServlet';
const postBody = {
Email: userDetails.username,
};
Expand Down Expand Up @@ -182,11 +178,11 @@ export function logout() {
* @param {object} credentials
* @param {string} credentials.username
* @param {string} credentials.password
* @param {function<Response>} failureCallback Callback provided reponse object.
* @param {function<Response>} failureCallback Callback provided response object.
* @return {Promise<Object>} User details if login is successful.
*/
export async function login(credentials, failureCallback = null) {
const url = `${API_URL}/cregLoginServlet`;
const url = '/bin/bhhs/cregLoginServlet';
let error;
try {
const resp = await fetch(url, {
Expand Down
2 changes: 1 addition & 1 deletion tools/sidekick/library.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
const library = document.createElement('sidekick-library')
library.config = {
base: '/tools/sidekick/library.json',
}
}
document.body.prepend(library)
</script>
</body>
Expand Down
Loading