Skip to content
This repository has been archived by the owner on Jan 19, 2024. It is now read-only.

Commit

Permalink
fix(demarches-simplifies): check if url exists via HEAD request (#252)
Browse files Browse the repository at this point in the history
* fix(demarches-simplifies): check url with url-exist

* fix: up

* chore: up

* fix: up

* fix: up
  • Loading branch information
rap2hpoutre authored Sep 27, 2022
1 parent f68e363 commit 14fbc8f
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 58 deletions.
27 changes: 14 additions & 13 deletions src/__tests__/cron/validate-dossier.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,20 @@ describe("validateDossier", () => {
});

it.each`
input | isValid
${undefined} | ${true}
${null} | ${true}
${""} | ${true}
${"non"} | ${false}
${"doctolib"} | ${false}
${"doctolib."} | ${false}
${"doctolib. com"} | ${false}
${"doctolib/com"} | ${false}
${"shouldBeValid.com"} | ${false}
${"https://valid.com"} | ${true}
${"http://valid.com"} | ${true}
${"http://VALID.com"} | ${true}
input | isValid
${undefined} | ${true}
${null} | ${true}
${""} | ${true}
${"non"} | ${false}
${"doctolib"} | ${false}
${"doctolib."} | ${false}
${"doctolib. com"} | ${false}
${"doctolib/com"} | ${false}
${"example.org"} | ${true}
${"www.example.org"} | ${true}
${"https://example.org"} | ${true}
${"http://example.org"} | ${true}
${"http://EXAMPLE.org"} | ${true}
`("should handle website error", async ({ input, isValid }) => {
const errors = await validateDossier(
{
Expand Down
13 changes: 13 additions & 0 deletions src/cron/demarchesSimplifiees.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from "../services/psychologists";
import { AdeliData } from "../types/adeli";
import { Psychologist } from "../types/psychologist";
import { urlExists } from "../utils/url-exists";

const limit = pLimit(5);

Expand Down Expand Up @@ -111,6 +112,18 @@ export const validateDossier = async (
);
}

if (dossier.website) {
const urlWithProtocol: string = dossier.website?.startsWith("http")
? dossier.website
: `https://${dossier.website}`;
const isUrlValid = await urlExists(urlWithProtocol);
if (!isUrlValid) {
errors.push(
`Le site web renseigné (${dossier.website}) n'est pas valide`
);
}
}

const identifier = dossier.id?.toString() ?? dossier.email;
const coordinates = await getAddressCoordinates(identifier, dossier.address);
if (!coordinates) {
Expand Down
34 changes: 0 additions & 34 deletions src/services/__tests__/validation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
psychologistLastNameDoesNotMatchMessage,
validatePsychologist,
ValidationAdeliData,
webSiteIsInvalidMessage,
} from "../demarchesSimplifiees/validate-psychologist";

describe("validatePsychologist", () => {
Expand Down Expand Up @@ -159,37 +158,4 @@ describe("validatePsychologist", () => {
candidateIsNotAPsychologistMessage("73")
);
});

it("should fail when website is wrong", () => {
const invalidPsychologists: CandidatePsychologist[] = [
{
...validPsychologist,
website: "abcdefg",
},
{
...validPsychologist,
website: "www.example.org",
},
];

for (const invalidPsychologist of invalidPsychologists) {
const validation = validatePsychologist(invalidPsychologist, [adeliData]);
assertIsValidationError(validation);

expect(validation.error.issues[0]?.message).toEqual(
webSiteIsInvalidMessage(invalidPsychologist.website)
);
}
});

it("should work when website is ok", () => {
const { success } = validatePsychologist(
{
...validPsychologist,
website: "https://example.org",
},
[adeliData]
);
expect(success).toBe(true);
});
});
11 changes: 0 additions & 11 deletions src/services/demarchesSimplifiees/validate-psychologist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,6 @@ export const validatePsychologist = (
return z
.object({
psychologist: z.object({
website: z
.optional(
z
.string()
.url(webSiteIsInvalidMessage(psychologist.website))
.or(z.literal(""))
)
.or(z.literal("")),
lastName: validateWithAdeliData({
adeliData,
message: psychologistLastNameDoesNotMatchMessage,
Expand Down Expand Up @@ -126,6 +118,3 @@ export const candidateIsNotAPsychologistMessage = (code) =>

export const emailIsInvalidMessage = (email) =>
`L'email renseigné (${email}) n'est pas valide`;

export const webSiteIsInvalidMessage = (url) =>
`Le site web renseigné (${url}) n'est pas valide`;
51 changes: 51 additions & 0 deletions src/utils/url-exists.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Source: https://stackoverflow.com/questions/35756479/does-jest-support-es6-import-export
import http from "http";
import { URL } from "url";

// https://github.com/sindresorhus/is-url-superb/blob/main/index.js
function isUrl(str: string): boolean {
if (typeof str !== "string") {
return false;
}

const trimmedStr = str.trim();
if (trimmedStr.includes(" ")) {
return false;
}

try {
new URL(str);
return true;
} catch {
return false;
}
}

// https://github.com/Richienb/url-exist/blob/master/index.js
export function urlExists(url: string): Promise<boolean> {
return new Promise((resolve) => {
if (!isUrl(url)) {
return resolve(false);
}

const { host, pathname } = new URL(url.trim());

const options = {
method: "HEAD",
host,
path: pathname,
timeout: 2000,
};

const req = http.request(options, (res) => {
resolve(res.statusCode < 400);
});
req.on("error", () => resolve(false));
req.on("timeout", () => {
req.destroy();
resolve(false);
});

req.end();
});
}

0 comments on commit 14fbc8f

Please sign in to comment.